From 0a4ff82af0f98ecf4ead70ce43a85bb91fec3d7d Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 15 Apr 2021 13:47:46 -0500 Subject: [PATCH 01/28] Added SecretsManager Added ISecrets Added ISecretsProvider --- PepperDashEssentials/ControlSystem.cs | 1 + .../Comm and IR/GenericComm.cs | 1 + .../Config/DeviceConfig.cs | 14 +- .../Factory/DeviceFactory.cs | 98 ++++++-- .../PepperDash_Essentials_Core.csproj | 4 + .../Secrets/CrestronSecretsProvider.cs | 84 +++++++ .../Secrets/Interfaces.cs | 18 ++ .../Secrets/SecretsManager.cs | 220 ++++++++++++++++++ .../Secrets/SecretsPropertiesConfig.cs | 17 ++ 9 files changed, 438 insertions(+), 19 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsPropertiesConfig.cs diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 5df5c1a2..37ef79a8 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -36,6 +36,7 @@ namespace PepperDash.Essentials Thread.MaxNumberOfUserThreads = 400; Global.ControlSystem = this; DeviceManager.Initialize(this); + SecretsManager.Initialize(); SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/GenericComm.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/GenericComm.cs index 8380a290..7648a379 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/GenericComm.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/GenericComm.cs @@ -25,6 +25,7 @@ namespace PepperDash.Essentials.Core public GenericComm(DeviceConfig config) : base(config) { + PropertiesConfig = CommFactory.GetControlPropertiesConfig(config); var commPort = CommFactory.CreateCommForDevice(config); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs index bb95da01..1d9ed1c2 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs @@ -30,7 +30,19 @@ namespace PepperDash.Essentials.Core.Config [JsonProperty("properties")] [JsonConverter(typeof(DevicePropertiesConverter))] - public JToken Properties { get; set; } + public JToken Properties { get; set; } + + public DeviceConfig(DeviceConfig dc) + { + Key = dc.Key; + Uid = dc.Uid; + Name = dc.Name; + Group = dc.Group; + Type = dc.Type; + Properties = JToken.FromObject(dc.Properties); + } + + public DeviceConfig() {} } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index 3f38e2d5..a0108490 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -7,6 +7,8 @@ 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; @@ -91,24 +93,84 @@ namespace PepperDash.Essentials.Core /// /// /// - public static IKeyed GetDevice(DeviceConfig dc) - { - var key = dc.Key; - var name = dc.Name; - var type = dc.Type; - var properties = dc.Properties; - - var typeName = dc.Type.ToLower(); - - // Check for types that have been added by plugin dlls. - if (FactoryMethods.ContainsKey(typeName)) - { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading '{0}' from Essentials Core", dc.Type); - return FactoryMethods[typeName].FactoryMethod(dc); - } - - return null; - } + public static IKeyed GetDevice(DeviceConfig dc) + { + try + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading '{0}' from Essentials Core", dc.Type); + + var localDc = new DeviceConfig(dc); + + var key = localDc.Key; + var name = localDc.Name; + var type = localDc.Type; + var properties = localDc.Properties; + + + + var typeName = localDc.Type.ToLower(); + + Debug.Console(2, "typeName = {0}", typeName); + // Check for types that have been added by plugin dlls. + if (FactoryMethods.ContainsKey(typeName)) + { + //look for secret in username + var userSecretToken = properties["control"]["tcpSshProperties"]["username"]["secret"]; + + if (userSecretToken != null) + { + Debug.Console(2, "Found a secret for {0} - attempting to retrieve it!", name); + var userSecretResult = + JsonConvert.DeserializeObject(userSecretToken.ToString()); + var userProvider = SecretsManager.GetSecretProviderByKey(userSecretResult.Provider); + if (userProvider != null) + { + var user = userProvider.GetSecret(userSecretResult.Key); + if (user == null) + { + Debug.Console(1, + "Unable to retrieve secret for {0} - Make sure you've added it to the secrets provider"); + return null; + } + properties["control"]["tcpSshProperties"]["username"] = (string) user.Value; + } + } + + //look for secret in password + var passwordSecretToken = properties["control"]["tcpSshProperties"]["password"]["secret"]; + + if (passwordSecretToken != null) + { + Debug.Console(2, "Found a secret for {0} - attempting to retrieve it!", name); + + var passwordSecretResult = + JsonConvert.DeserializeObject(passwordSecretToken.ToString()); + var passwordProvider = SecretsManager.GetSecretProviderByKey(passwordSecretResult.Provider); + if (passwordProvider != null) + { + var password = passwordProvider.GetSecret(passwordSecretResult.Key); + if (password == null) + { + Debug.Console(1, + "Unable to retrieve secret for {0} - Make sure you've added it to the secrets provider"); + return null; + } + properties["control"]["tcpSshProperties"]["password"] = (string) password.Value; + } + } + + Debug.Console(0, "{0}", localDc.Properties.ToString()); + + return FactoryMethods[typeName].FactoryMethod(localDc); + } + return null; + } + catch (Exception ex) + { + Debug.Console(2, "Issue with getting device - {0}", ex.Message); + return null; + } + } /// /// Prints the type names and associated metadata from the FactoryMethods collection. diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index e4c775d0..f202434e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -320,6 +320,10 @@ + + + + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs new file mode 100644 index 00000000..54a3f3c8 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs @@ -0,0 +1,84 @@ +using System; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronDataStore; +using PepperDash.Core; + + +namespace PepperDash.Essentials.Core +{ + public class CrestronSecretsProvider : ISecretProvider + { + public string Key { get; set; } + //Added for reference + //private readonly bool _secureSupported; + public CrestronSecretsProvider(string key) + { + Key = key; + //Added for future encrypted reference + //_secureSupported = CrestronSecureStorage.Supported; + + //if (_secureSupported) + //{ + // return; + //} + CrestronDataStoreStatic.InitCrestronDataStore(); + + } + + + public void SetSecret(string key, object value) + { + var secret = value as string; + if (String.IsNullOrEmpty(secret)) + { + Debug.Console(2, this, "Unable to set secret for {0}:{1} - value is empty.", Key, key); + return; + } + Debug.Console(2, this, "Attempting to set Secret to {0}", secret); + var setErrorCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); + switch (setErrorCode) + { + case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: + Debug.Console(2, this,"Secret Successfully Set for {0}:{1}", Key, key); + break; + default: + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, setErrorCode.ToString()); + break; + } + } + + public ISecret GetSecret(string key) + { + string mySecret; + var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret); + + switch (getErrorCode) + { + case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: + Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key); + Debug.Console(2, this, "Retreived Secret = {0}", mySecret); + return new CrestronSecret(key, mySecret, this); + default: + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", + Key, key, getErrorCode.ToString()); + return null; + } + } + } + + public class CrestronSecret : ISecret + { + public ISecretProvider Provider { get; private set; } + public string Key { get; private set; } + + public object Value { get; private set; } + + public CrestronSecret(string key, string value, ISecretProvider provider) + { + Key = key; + Value = value; + Provider = provider; + } + + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs new file mode 100644 index 00000000..51b0b389 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs @@ -0,0 +1,18 @@ +using PepperDash.Core; + +namespace PepperDash.Essentials.Core +{ + public interface ISecretProvider : IKeyed + { + void SetSecret(string key, object value); + + ISecret GetSecret(string key); + } + + public interface ISecret + { + ISecretProvider Provider { get; } + string Key { get; } + object Value { get; } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs new file mode 100644 index 00000000..c14bfdc6 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Crestron.SimplSharp; +using PepperDash.Core; + + +namespace PepperDash.Essentials.Core +{ + public static class SecretsManager + { + public static List Secrets { get; set; } + + public static void Initialize() + { + Secrets = new List {new CrestronSecretsProvider("default")}; + + CrestronConsole.AddNewConsoleCommand(SetSecretProcess, "setsecret", + "Adds secrets to secret provider", + ConsoleAccessLevelEnum.AccessOperator); + + CrestronConsole.AddNewConsoleCommand(UpdateSecretProcess, "updatesecret", + "Updates secrets in secret provider", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(DeleteSecretProcess, "deletesecret", + "Deletes secrets in secret provider", + ConsoleAccessLevelEnum.AccessAdministrator); + + + } + + public static ISecretProvider GetSecretProviderByKey(string key) + { + var secret = Secrets.FirstOrDefault(o => o.Key == key); + if (secret == null) + { + Debug.Console(1, "SecretsManager unable to retrieve SecretProvider with the key '{0}'", key); + } + return secret; + } + + private static void SetSecretProcess(string cmd) + { + string response; + var args = cmd.Split(' '); + + if (args.Length == 0) + { + //some Instructional Text + response = "Adds secrets to secret provider. Format 'setsecret "; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + if (args.Length == 1 && args[0] == "?") + { + response = "Adds secrets to secret provider. Format 'setsecret "; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + if (args.Length < 3) + { + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + var provider = Secrets.FirstOrDefault(o => o.Key == args[0]); + + if (provider == null) + { + //someFail + response = "Provider key invalid"; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + var key = args[1]; + var secret = args[2]; + + if (provider.GetSecret(key) == null) + { + provider.SetSecret(key, secret); + response = + String.Format( + "Secret successfully set for {0}:{1}", + provider.Key, key); + CrestronConsole.ConsoleCommandResponse(response); + return; + } + response = + String.Format( + "Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it"); + CrestronConsole.ConsoleCommandResponse(response); + } + + private static void UpdateSecretProcess(string cmd) + { + string response; + var args = cmd.Split(' '); + + if (args.Length == 0) + { + //some Instructional Text + response = "Updates secrets in secret provider. Format 'updatesecret "; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + if (args.Length == 1 && args[0] == "?") + { + response = "Updates secrets in secret provider. Format 'updatesecret "; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + + if (args.Length < 3) + { + //someFail + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + var provider = Secrets.FirstOrDefault(o => o.Key == args[0]); + + if (provider == null) + { + //someFail + response = "Provider key invalid"; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + var key = args[1]; + var secret = args[2]; + + if (provider.GetSecret(key) != null) + { + provider.SetSecret(key, secret); + response = + String.Format( + "Secret successfully updated for {0}:{1}", + provider.Key, key); + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + response = + String.Format( + "Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to create a new secret"); + CrestronConsole.ConsoleCommandResponse(response); + } + + private static void DeleteSecretProcess(string cmd) + { + string response; + var args = cmd.Split(' '); + + if (args.Length == 0) + { + //some Instructional Text + response = "Deletes secrets in secret provider. Format 'deletesecret "; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + if (args.Length == 1 && args[0] == "?") + { + response = "Deletes secrets in secret provider. Format 'deletesecret "; + CrestronConsole.ConsoleCommandResponse(response); + return; + } + + + + if (args.Length < 2) + { + //someFail + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + var provider = Secrets.FirstOrDefault(o => o.Key == args[0]); + + if (provider == null) + { + //someFail + response = "Provider key invalid"; + CrestronConsole.ConsoleCommandResponse(response); + return; + + } + + var key = args[1]; + + + provider.SetSecret(key, ""); + response = + String.Format( + "Secret successfully deleted for {0}:{1}", + provider.Key, key); + CrestronConsole.ConsoleCommandResponse(response); + + + } + } + + +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsPropertiesConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsPropertiesConfig.cs new file mode 100644 index 00000000..b17b9000 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsPropertiesConfig.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Core +{ + public class SecretsPropertiesConfig + { + [JsonProperty("provider")] + public string Provider { get; set; } + [JsonProperty("key")] + public string Key { get; set; } + } +} \ No newline at end of file From babc3e4f1a9cf46e8bfdf0d5677a285f350f477d Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 15 Apr 2021 14:36:43 -0500 Subject: [PATCH 02/28] fixed minor registration error --- .../Extensions/JsonExtensions.cs | 42 ++++++++ .../Factory/DeviceFactory.cs | 99 ++++++++++--------- .../PepperDash_Essentials_Core.csproj | 1 + 3 files changed, 94 insertions(+), 48 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/JsonExtensions.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/JsonExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/JsonExtensions.cs new file mode 100644 index 00000000..cdf723ea --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/JsonExtensions.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace PepperDash.Essentials.Core +{ + public static class JsonExtensions + { + public static List FindTokens(this JToken containerToken, string name) + { + List matches = new List(); + FindTokens(containerToken, name, matches); + return matches; + } + + private static void FindTokens(JToken containerToken, string name, List matches) + { + if (containerToken.Type == JTokenType.Object) + { + foreach (JProperty child in containerToken.Children()) + { + if (child.Name == name) + { + matches.Add(child.Value); + } + FindTokens(child.Value, name, matches); + } + } + else if (containerToken.Type == JTokenType.Array) + { + foreach (JToken child in containerToken.Children()) + { + FindTokens(child, name, matches); + } + } + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index a0108490..cb7dd0b7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -105,65 +105,68 @@ namespace PepperDash.Essentials.Core var name = localDc.Name; var type = localDc.Type; var properties = localDc.Properties; - - + //var propRecurse = properties; var typeName = localDc.Type.ToLower(); Debug.Console(2, "typeName = {0}", typeName); // Check for types that have been added by plugin dlls. - if (FactoryMethods.ContainsKey(typeName)) + if (!FactoryMethods.ContainsKey(typeName)) return null; + + /*foreach (var obj in (propRecurse as JObject).FindTokens("secret").OfType()) + { + Debug.Console(2, obj.ToString()); + }*/ + + + //look for secret in username + var userSecretToken = properties["control"]["tcpSshProperties"]["username"]["secret"]; + + if (userSecretToken != null) { - //look for secret in username - var userSecretToken = properties["control"]["tcpSshProperties"]["username"]["secret"]; - - if (userSecretToken != null) + Debug.Console(2, "Found a secret for {0} - attempting to retrieve it!", name); + var userSecretResult = + JsonConvert.DeserializeObject(userSecretToken.ToString()); + var userProvider = SecretsManager.GetSecretProviderByKey(userSecretResult.Provider); + if (userProvider != null) { - Debug.Console(2, "Found a secret for {0} - attempting to retrieve it!", name); - var userSecretResult = - JsonConvert.DeserializeObject(userSecretToken.ToString()); - var userProvider = SecretsManager.GetSecretProviderByKey(userSecretResult.Provider); - if (userProvider != null) + var user = userProvider.GetSecret(userSecretResult.Key); + if (user == null) { - var user = userProvider.GetSecret(userSecretResult.Key); - if (user == null) - { - Debug.Console(1, - "Unable to retrieve secret for {0} - Make sure you've added it to the secrets provider"); - return null; - } - properties["control"]["tcpSshProperties"]["username"] = (string) user.Value; + Debug.Console(1, + "Unable to retrieve secret for {0} - Make sure you've added it to the secrets provider"); + return null; } + properties["control"]["tcpSshProperties"]["username"] = (string) user.Value; } - - //look for secret in password - var passwordSecretToken = properties["control"]["tcpSshProperties"]["password"]["secret"]; - - if (passwordSecretToken != null) - { - Debug.Console(2, "Found a secret for {0} - attempting to retrieve it!", name); - - var passwordSecretResult = - JsonConvert.DeserializeObject(passwordSecretToken.ToString()); - var passwordProvider = SecretsManager.GetSecretProviderByKey(passwordSecretResult.Provider); - if (passwordProvider != null) - { - var password = passwordProvider.GetSecret(passwordSecretResult.Key); - if (password == null) - { - Debug.Console(1, - "Unable to retrieve secret for {0} - Make sure you've added it to the secrets provider"); - return null; - } - properties["control"]["tcpSshProperties"]["password"] = (string) password.Value; - } - } - - Debug.Console(0, "{0}", localDc.Properties.ToString()); - - return FactoryMethods[typeName].FactoryMethod(localDc); } - return null; + + //look for secret in password + var passwordSecretToken = properties["control"]["tcpSshProperties"]["password"]["secret"]; + + if (passwordSecretToken != null) + { + Debug.Console(2, "Found a secret for {0} - attempting to retrieve it!", name); + + var passwordSecretResult = + JsonConvert.DeserializeObject(passwordSecretToken.ToString()); + var passwordProvider = SecretsManager.GetSecretProviderByKey(passwordSecretResult.Provider); + if (passwordProvider != null) + { + var password = passwordProvider.GetSecret(passwordSecretResult.Key); + if (password == null) + { + Debug.Console(1, + "Unable to retrieve secret for {0} - Make sure you've added it to the secrets provider"); + return null; + } + properties["control"]["tcpSshProperties"]["password"] = (string)password.Value; + } + } + + Debug.Console(0, "{0}", localDc.Properties.ToString()); + + return FactoryMethods[typeName].FactoryMethod(localDc); } catch (Exception ex) { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index f202434e..e65b081b 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -209,6 +209,7 @@ + From 2787c7fc523551eb76d05d75aefd33f63c7a99c0 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 15 Apr 2021 18:47:13 -0500 Subject: [PATCH 03/28] Close #685 Adds support for Secrets --- .../Factory/DeviceFactory.cs | 147 ++++++++---------- .../Secrets/CrestronSecretsProvider.cs | 16 +- .../Secrets/Interfaces.cs | 6 + .../Secrets/SecretsManager.cs | 8 + .../Secrets/SecretsPropertiesConfig.cs | 3 + 5 files changed, 95 insertions(+), 85 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index cb7dd0b7..66bf5d2b 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -85,96 +85,79 @@ namespace PepperDash.Essentials.Core var wrapper = new DeviceFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method }; DeviceFactory.FactoryMethods.Add(typeName, wrapper); - } - - /// - /// The factory method for Core "things". Also iterates the Factory methods that have - /// been loaded from plugins - /// - /// - /// - public static IKeyed GetDevice(DeviceConfig dc) - { - try - { + } + + private static void CheckForSecrets(IEnumerable obj) + { + foreach (var prop in obj.Where(prop => prop.Value as JObject != null)) + { + if (prop.Name.ToLower() == "secret") + { + var secret = GetSecret(JsonConvert.DeserializeObject(prop.Children().First().ToString())); + prop.Parent.Replace(secret); + } + var recurseProp = prop.Value as JObject; + if (recurseProp == null) return; + CheckForSecrets(recurseProp.Properties()); + } + } + + private static string GetSecret(SecretsPropertiesConfig data) + { + var secretProvider = SecretsManager.GetSecretProviderByKey(data.Provider); + if (secretProvider == null) return null; + var secret = secretProvider.GetSecret(data.Key); + if (secret != null) return (string) secret.Value; + Debug.Console(1, + "Unable to retrieve secret {0}{1} - Make sure you've added it to the secrets provider", + data.Provider, data.Key); + return null; + } + + + /// + /// The factory method for Core "things". Also iterates the Factory methods that have + /// been loaded from plugins + /// + /// + /// + public static + IKeyed GetDevice(DeviceConfig dc) + { + try + { Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading '{0}' from Essentials Core", dc.Type); - var localDc = new DeviceConfig(dc); + var localDc = new DeviceConfig(dc); - var key = localDc.Key; - var name = localDc.Name; - var type = localDc.Type; + var key = localDc.Key; + var name = localDc.Name; + var type = localDc.Type; var properties = localDc.Properties; - //var propRecurse = properties; + //var propRecurse = properties; - var typeName = localDc.Type.ToLower(); + var typeName = localDc.Type.ToLower(); + + + var jObject = properties as JObject; + if (jObject != null) + { + var jProp = jObject.Properties(); + + CheckForSecrets(jProp); + } Debug.Console(2, "typeName = {0}", typeName); - // Check for types that have been added by plugin dlls. - if (!FactoryMethods.ContainsKey(typeName)) return null; + // Check for types that have been added by plugin dlls. + return !FactoryMethods.ContainsKey(typeName) ? null : FactoryMethods[typeName].FactoryMethod(localDc); + } + catch (Exception ex) + { + Debug.Console(2, "Issue with getting device - {0}", ex.Message); + return null; + } + } - /*foreach (var obj in (propRecurse as JObject).FindTokens("secret").OfType()) - { - Debug.Console(2, obj.ToString()); - }*/ - - - //look for secret in username - var userSecretToken = properties["control"]["tcpSshProperties"]["username"]["secret"]; - - if (userSecretToken != null) - { - Debug.Console(2, "Found a secret for {0} - attempting to retrieve it!", name); - var userSecretResult = - JsonConvert.DeserializeObject(userSecretToken.ToString()); - var userProvider = SecretsManager.GetSecretProviderByKey(userSecretResult.Provider); - if (userProvider != null) - { - var user = userProvider.GetSecret(userSecretResult.Key); - if (user == null) - { - Debug.Console(1, - "Unable to retrieve secret for {0} - Make sure you've added it to the secrets provider"); - return null; - } - properties["control"]["tcpSshProperties"]["username"] = (string) user.Value; - } - } - - //look for secret in password - var passwordSecretToken = properties["control"]["tcpSshProperties"]["password"]["secret"]; - - if (passwordSecretToken != null) - { - Debug.Console(2, "Found a secret for {0} - attempting to retrieve it!", name); - - var passwordSecretResult = - JsonConvert.DeserializeObject(passwordSecretToken.ToString()); - var passwordProvider = SecretsManager.GetSecretProviderByKey(passwordSecretResult.Provider); - if (passwordProvider != null) - { - var password = passwordProvider.GetSecret(passwordSecretResult.Key); - if (password == null) - { - Debug.Console(1, - "Unable to retrieve secret for {0} - Make sure you've added it to the secrets provider"); - return null; - } - properties["control"]["tcpSshProperties"]["password"] = (string)password.Value; - } - } - - Debug.Console(0, "{0}", localDc.Properties.ToString()); - - return FactoryMethods[typeName].FactoryMethod(localDc); - } - catch (Exception ex) - { - Debug.Console(2, "Issue with getting device - {0}", ex.Message); - return null; - } - } - /// /// Prints the type names and associated metadata from the FactoryMethods collection. /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs index 54a3f3c8..87dddea7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs @@ -25,7 +25,11 @@ namespace PepperDash.Essentials.Core } - + /// + /// Set secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// Secret Value public void SetSecret(string key, object value) { var secret = value as string; @@ -34,7 +38,6 @@ namespace PepperDash.Essentials.Core Debug.Console(2, this, "Unable to set secret for {0}:{1} - value is empty.", Key, key); return; } - Debug.Console(2, this, "Attempting to set Secret to {0}", secret); var setErrorCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); switch (setErrorCode) { @@ -47,6 +50,11 @@ namespace PepperDash.Essentials.Core } } + /// + /// Retrieve secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// ISecret Object containing key, provider, and value public ISecret GetSecret(string key) { string mySecret; @@ -56,7 +64,6 @@ namespace PepperDash.Essentials.Core { case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key); - Debug.Console(2, this, "Retreived Secret = {0}", mySecret); return new CrestronSecret(key, mySecret, this); default: Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", @@ -66,6 +73,9 @@ namespace PepperDash.Essentials.Core } } + /// + /// Special container class for CrestronSecret provider + /// public class CrestronSecret : ISecret { public ISecretProvider Provider { get; private set; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs index 51b0b389..86ae65cf 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs @@ -2,6 +2,9 @@ namespace PepperDash.Essentials.Core { + /// + /// All ISecrecretProvider classes must implement this interface. + /// public interface ISecretProvider : IKeyed { void SetSecret(string key, object value); @@ -9,6 +12,9 @@ namespace PepperDash.Essentials.Core ISecret GetSecret(string key); } + /// + /// interface for delivering secrets in Essentials. + /// public interface ISecret { ISecretProvider Provider { get; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs index c14bfdc6..f50051da 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs @@ -11,6 +11,9 @@ namespace PepperDash.Essentials.Core { public static List Secrets { get; set; } + /// + /// Initialize the SecretsManager + /// public static void Initialize() { Secrets = new List {new CrestronSecretsProvider("default")}; @@ -30,6 +33,11 @@ namespace PepperDash.Essentials.Core } + /// + /// Method to return a ISecretProvider to Set, Get, and Delete Secrets + /// + /// Secret Provider Key + /// public static ISecretProvider GetSecretProviderByKey(string key) { var secret = Secrets.FirstOrDefault(o => o.Key == key); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsPropertiesConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsPropertiesConfig.cs index b17b9000..68026aa1 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsPropertiesConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsPropertiesConfig.cs @@ -7,6 +7,9 @@ using Newtonsoft.Json; namespace PepperDash.Essentials.Core { + /// + /// Provide a way to easily deserialize into a secret object from config + /// public class SecretsPropertiesConfig { [JsonProperty("provider")] From 8643ed2cafbd32a737019500bf2aaf82d6727477 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Thu, 15 Apr 2021 19:14:24 -0500 Subject: [PATCH 04/28] #685 - Requested Fixes per AWelker --- .../Secrets/CrestronSecretsProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs index 87dddea7..609aba64 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs @@ -66,9 +66,9 @@ namespace PepperDash.Essentials.Core Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key); return new CrestronSecret(key, mySecret, this); default: - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", Key, key, getErrorCode.ToString()); - return null; + return new CrestronSecret(key, String.Empty, this); } } } From 452d0a5a398395eff15f2145cdbdf513dfdda00d Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Apr 2021 09:59:58 -0500 Subject: [PATCH 05/28] Changed DeviceFactory.GetSecret(SecretsPropertiesConfig data) to return an empty string instead of null on a failed retrieval --- .../PepperDashEssentialsBase/Factory/DeviceFactory.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index 66bf5d2b..d4382442 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -111,7 +111,7 @@ namespace PepperDash.Essentials.Core Debug.Console(1, "Unable to retrieve secret {0}{1} - Make sure you've added it to the secrets provider", data.Provider, data.Key); - return null; + return String.Empty; } @@ -121,8 +121,7 @@ namespace PepperDash.Essentials.Core /// /// /// - public static - IKeyed GetDevice(DeviceConfig dc) + public static IKeyed GetDevice(DeviceConfig dc) { try { From 3c9ca1e527b19bb72c4835ccdbd22336c1fed180 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Apr 2021 12:29:41 -0500 Subject: [PATCH 06/28] Resoves #688 Added some QoL improvements to SecretsManager meant to protect the integrity of the providers dictionary from accidental manipulation Debug statement improvements Improvements to verbosity of console command returns for the SecretsManager --- .../Factory/DeviceFactory.cs | 7 +- .../Secrets/CrestronSecretsProvider.cs | 29 +++--- .../Secrets/Interfaces.cs | 2 +- .../Secrets/SecretsManager.cs | 97 ++++++++++++++----- 4 files changed, 97 insertions(+), 38 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index d4382442..ec041853 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -93,7 +93,8 @@ namespace PepperDash.Essentials.Core { if (prop.Name.ToLower() == "secret") { - var secret = GetSecret(JsonConvert.DeserializeObject(prop.Children().First().ToString())); + var secret = GetSecret(prop.Children().First().ToObject()); + //var secret = GetSecret(JsonConvert.DeserializeObject(prop.Children().First().ToString())); prop.Parent.Replace(secret); } var recurseProp = prop.Value as JObject; @@ -152,7 +153,9 @@ namespace PepperDash.Essentials.Core } catch (Exception ex) { - Debug.Console(2, "Issue with getting device - {0}", ex.Message); + Debug.Console(0, Debug.ErrorLogLevel.Error, "Exception occurred while creating device {0}: {1}", dc.Key, ex.Message); + + Debug.Console(2, "{0}", ex.StackTrace); return null; } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs index 609aba64..3e0a5964 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/CrestronSecretsProvider.cs @@ -10,19 +10,22 @@ namespace PepperDash.Essentials.Core { public string Key { get; set; } //Added for reference - //private readonly bool _secureSupported; + private static readonly bool SecureSupported; public CrestronSecretsProvider(string key) { Key = key; + } + + static CrestronSecretsProvider() + { //Added for future encrypted reference - //_secureSupported = CrestronSecureStorage.Supported; + SecureSupported = CrestronSecureStorage.Supported; - //if (_secureSupported) - //{ - // return; - //} CrestronDataStoreStatic.InitCrestronDataStore(); - + if (SecureSupported) + { + //doThingsFuture + } } /// @@ -30,23 +33,23 @@ namespace PepperDash.Essentials.Core /// /// Secret Key /// Secret Value - public void SetSecret(string key, object value) + public bool SetSecret(string key, object value) { var secret = value as string; if (String.IsNullOrEmpty(secret)) { Debug.Console(2, this, "Unable to set secret for {0}:{1} - value is empty.", Key, key); - return; + return false; } var setErrorCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); switch (setErrorCode) { case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: - Debug.Console(2, this,"Secret Successfully Set for {0}:{1}", Key, key); - break; + Debug.Console(1, this,"Secret Successfully Set for {0}:{1}", Key, key); + return true; default: Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, setErrorCode.ToString()); - break; + return false; } } @@ -68,7 +71,7 @@ namespace PepperDash.Essentials.Core default: Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}", Key, key, getErrorCode.ToString()); - return new CrestronSecret(key, String.Empty, this); + return null; } } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs index 86ae65cf..43c6a230 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/Interfaces.cs @@ -7,7 +7,7 @@ namespace PepperDash.Essentials.Core /// public interface ISecretProvider : IKeyed { - void SetSecret(string key, object value); + bool SetSecret(string key, object value); ISecret GetSecret(string key); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs index f50051da..bcb46ff5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using Crestron.SimplSharp; using PepperDash.Core; @@ -9,15 +8,16 @@ namespace PepperDash.Essentials.Core { public static class SecretsManager { - public static List Secrets { get; set; } + public static Dictionary Secrets { get; private set; } /// /// Initialize the SecretsManager /// public static void Initialize() { - Secrets = new List {new CrestronSecretsProvider("default")}; - + + AddSecretProvider("default", new CrestronSecretsProvider("default")); + CrestronConsole.AddNewConsoleCommand(SetSecretProcess, "setsecret", "Adds secrets to secret provider", ConsoleAccessLevelEnum.AccessOperator); @@ -29,18 +29,24 @@ namespace PepperDash.Essentials.Core CrestronConsole.AddNewConsoleCommand(DeleteSecretProcess, "deletesecret", "Deletes secrets in secret provider", ConsoleAccessLevelEnum.AccessAdministrator); - + } + static SecretsManager() + { + Secrets = new Dictionary(); } /// - /// Method to return a ISecretProvider to Set, Get, and Delete Secrets + /// Get Secret Provider from dictionary by key /// - /// Secret Provider Key - /// + /// Dictionary Key for provider + /// ISecretProvider public static ISecretProvider GetSecretProviderByKey(string key) { - var secret = Secrets.FirstOrDefault(o => o.Key == key); + ISecretProvider secret; + + Secrets.TryGetValue(key, out secret); + if (secret == null) { Debug.Console(1, "SecretsManager unable to retrieve SecretProvider with the key '{0}'", key); @@ -48,6 +54,44 @@ namespace PepperDash.Essentials.Core return secret; } + /// + /// Add secret provider to secrets dictionary + /// + /// Key of new entry + /// New Provider Entry + public static void AddSecretProvider(string key, ISecretProvider provider) + { + if (!Secrets.ContainsKey(key)) + { + Secrets.Add(key, provider); + Debug.Console(1, "Secrets provider '{0}' added to SecretsManager", key); + } + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key ); + } + + /// + /// Add secret provider to secrets dictionary, with optional overwrite parameter + /// + /// Key of new entry + /// New provider entry + /// true to overwrite any existing providers in the dictionary + public static void AddSecretProvider(string key, ISecretProvider provider, bool overwrite) + { + if (!Secrets.ContainsKey(key)) + { + Secrets.Add(key, provider); + Debug.Console(1, "Secrets provider '{0}' added to SecretsManager", key); + + } + if (overwrite) + { + Secrets.Add(key, provider); + Debug.Console(1, Debug.ErrorLogLevel.Notice, "Provider with the key '{0}' already exists in secrets. Overwriting with new secrets provider.", key); + + } + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key); + } + private static void SetSecretProcess(string cmd) { string response; @@ -76,7 +120,7 @@ namespace PepperDash.Essentials.Core } - var provider = Secrets.FirstOrDefault(o => o.Key == args[0]); + var provider = GetSecretProviderByKey(args[0]); if (provider == null) { @@ -92,11 +136,14 @@ namespace PepperDash.Essentials.Core if (provider.GetSecret(key) == null) { - provider.SetSecret(key, secret); - response = - String.Format( + + response = provider.SetSecret(key, secret) + ? String.Format( "Secret successfully set for {0}:{1}", - provider.Key, key); + provider.Key, key) + : String.Format( + "Unable to set secret for {0}:{1}", + provider.Key, key); CrestronConsole.ConsoleCommandResponse(response); return; } @@ -137,7 +184,7 @@ namespace PepperDash.Essentials.Core } - var provider = Secrets.FirstOrDefault(o => o.Key == args[0]); + var provider = GetSecretProviderByKey(args[0]); if (provider == null) { @@ -153,10 +200,12 @@ namespace PepperDash.Essentials.Core if (provider.GetSecret(key) != null) { - provider.SetSecret(key, secret); - response = - String.Format( - "Secret successfully updated for {0}:{1}", + response = provider.SetSecret(key, secret) + ? String.Format( + "Secret successfully set for {0}:{1}", + provider.Key, key) + : String.Format( + "Unable to set secret for {0}:{1}", provider.Key, key); CrestronConsole.ConsoleCommandResponse(response); return; @@ -199,7 +248,7 @@ namespace PepperDash.Essentials.Core } - var provider = Secrets.FirstOrDefault(o => o.Key == args[0]); + var provider = GetSecretProviderByKey(args[0]); if (provider == null) { @@ -214,11 +263,15 @@ namespace PepperDash.Essentials.Core provider.SetSecret(key, ""); - response = - String.Format( + response = provider.SetSecret(key, "") + ? String.Format( "Secret successfully deleted for {0}:{1}", + provider.Key, key) + : String.Format( + "Unable to delete secret for {0}:{1}", provider.Key, key); CrestronConsole.ConsoleCommandResponse(response); + return; } From fb44a3b93ca71793bc4e84f7f293e14632466171 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 29 Apr 2021 13:44:47 -0400 Subject: [PATCH 07/28] Resolves looping in IRouting by adding the device to the tracking list before iterating down further. Adds debug statement to print when this condition occurs - "Skipping input on , this was already checked" --- .../Routing/IRoutingInputsExtensions.cs | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index e795018a..0c375825 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -123,25 +123,34 @@ namespace PepperDash.Essentials.Core // No direct tie? Run back out on the inputs' attached devices... // Only the ones that are routing devices var attachedMidpoints = destDevInputTies.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs); + + //Create a list for tracking already checked devices to avoid loops, if it doesn't already exist from previous iteration + if (alreadyCheckedDevices == null) + alreadyCheckedDevices = new List(); + alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs); + foreach (var inputTieToTry in attachedMidpoints) { - Debug.Console(2, destination, "Trying to find route on {0}", inputTieToTry.SourcePort.ParentDevice.Key); var upstreamDeviceOutputPort = inputTieToTry.SourcePort; var upstreamRoutingDevice = upstreamDeviceOutputPort.ParentDevice as IRoutingInputsOutputs; + Debug.Console(2, destination, "Trying to find route on {0}", upstreamRoutingDevice.Key); + // Check if this previous device has already been walked - if (!(alreadyCheckedDevices != null && alreadyCheckedDevices.Contains(upstreamRoutingDevice))) - { - // haven't seen this device yet. Do it. Pass the output port to the next - // level to enable switching on success - var upstreamRoutingSuccess = upstreamRoutingDevice.GetRouteToSource(source, upstreamDeviceOutputPort, - alreadyCheckedDevices, signalType, cycle, routeTable); - if (upstreamRoutingSuccess) - { - Debug.Console(2, destination, "Upstream device route found"); - goodInputPort = inputTieToTry.DestinationPort; - break; // Stop looping the inputs in this cycle - } - } + if (alreadyCheckedDevices.Contains(upstreamRoutingDevice)) + { + Debug.Console(2, destination, "Skipping input {0} on {1}, this was already checked", upstreamRoutingDevice.Key, destination.Key); + continue; + } + // haven't seen this device yet. Do it. Pass the output port to the next + // level to enable switching on success + var upstreamRoutingSuccess = upstreamRoutingDevice.GetRouteToSource(source, upstreamDeviceOutputPort, + alreadyCheckedDevices, signalType, cycle, routeTable); + if (upstreamRoutingSuccess) + { + Debug.Console(2, destination, "Upstream device route found"); + goodInputPort = inputTieToTry.DestinationPort; + break; // Stop looping the inputs in this cycle + } } } @@ -163,10 +172,6 @@ namespace PepperDash.Essentials.Core //Debug.Console(2, destination, "Exiting cycle {0}", cycle); return true; } - - if(alreadyCheckedDevices == null) - alreadyCheckedDevices = new List(); - alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs); Debug.Console(2, destination, "No route found to {0}", source.Key); return false; From 9ea65883b77fcaf90f02f83c6026cd51dc8c379a Mon Sep 17 00:00:00 2001 From: Jason Alborough Date: Fri, 30 Apr 2021 14:58:39 -0400 Subject: [PATCH 08/28] Fixes DM Audio Routing --- .../Chassis/DmChassisController.cs | 2796 ++++++++--------- 1 file changed, 1398 insertions(+), 1398 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index 72f84f48..8c6b2ced 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -1,324 +1,324 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharp; using Crestron.SimplSharp.Reflection; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; -using Crestron.SimplSharpPro.DM; -using Crestron.SimplSharpPro.DM.Cards; -using Crestron.SimplSharpPro.DM.Endpoints; -using Newtonsoft.Json; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.DM.Config; -using PepperDash.Essentials.Core.Config; - -namespace PepperDash.Essentials.DM -{ - /// - /// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions - /// - /// +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.DM; +using Crestron.SimplSharpPro.DM.Cards; +using Crestron.SimplSharpPro.DM.Endpoints; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.DM.Config; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.DM +{ + /// + /// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions + /// + /// [Description("Wrapper class for all DM-MD chassis variants from 8x8 to 32x32")] public class DmChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumericWithFeedback { - private const string NonePortKey = "inputCard0--None"; - public DMChassisPropertiesConfig PropertiesConfig { get; set; } - + private const string NonePortKey = "inputCard0--None"; + public DMChassisPropertiesConfig PropertiesConfig { get; set; } + public Switch Chassis { get; private set; } //IroutingNumericEvent - public event EventHandler NumericSwitchChange; - - // Feedbacks for EssentialDM - public Dictionary VideoOutputFeedbacks { get; private set; } - public Dictionary AudioOutputFeedbacks { get; private set; } - public Dictionary VideoInputSyncFeedbacks { get; private set; } - public Dictionary InputEndpointOnlineFeedbacks { get; private set; } - public Dictionary OutputEndpointOnlineFeedbacks { get; private set; } - public Dictionary InputNameFeedbacks { get; private set; } - public Dictionary OutputNameFeedbacks { get; private set; } - public Dictionary OutputVideoRouteNameFeedbacks { get; private set; } - public Dictionary OutputAudioRouteNameFeedbacks { get; private set; } - public Dictionary UsbOutputRoutedToFeebacks { get; private set; } - public Dictionary UsbInputRoutedToFeebacks { get; private set; } - public Dictionary OutputDisabledByHdcpFeedbacks { get; private set; } - - public IntFeedback SystemIdFeebdack { get; private set; } - public BoolFeedback SystemIdBusyFeedback { get; private set; } - public BoolFeedback EnableAudioBreakawayFeedback { get; private set; } - public BoolFeedback EnableUsbBreakawayFeedback { get; private set; } - + public event EventHandler NumericSwitchChange; + + // Feedbacks for EssentialDM + public Dictionary VideoOutputFeedbacks { get; private set; } + public Dictionary AudioOutputFeedbacks { get; private set; } + public Dictionary VideoInputSyncFeedbacks { get; private set; } + public Dictionary InputEndpointOnlineFeedbacks { get; private set; } + public Dictionary OutputEndpointOnlineFeedbacks { get; private set; } + public Dictionary InputNameFeedbacks { get; private set; } + public Dictionary OutputNameFeedbacks { get; private set; } + public Dictionary OutputVideoRouteNameFeedbacks { get; private set; } + public Dictionary OutputAudioRouteNameFeedbacks { get; private set; } + public Dictionary UsbOutputRoutedToFeebacks { get; private set; } + public Dictionary UsbInputRoutedToFeebacks { get; private set; } + public Dictionary OutputDisabledByHdcpFeedbacks { get; private set; } + + public IntFeedback SystemIdFeebdack { get; private set; } + public BoolFeedback SystemIdBusyFeedback { get; private set; } + public BoolFeedback EnableAudioBreakawayFeedback { get; private set; } + public BoolFeedback EnableUsbBreakawayFeedback { get; private set; } + public Dictionary InputCardHdcpStateFeedbacks { get; private set; } public Dictionary InputStreamCardStateFeedbacks { get; private set; } - public Dictionary OutputStreamCardStateFeedbacks { get; private set; } - - public Dictionary InputCardHdcpCapabilityTypes { get; private set; } - - // Need a couple Lists of generic Backplane ports - public RoutingPortCollection InputPorts { get; private set; } - public RoutingPortCollection OutputPorts { get; private set; } - - public Dictionary TxDictionary { get; set; } - public Dictionary RxDictionary { get; set; } - - //public Dictionary InputCards { get; private set; } - //public Dictionary OutputCards { get; private set; } - - public Dictionary InputNames { get; set; } - public Dictionary OutputNames { get; set; } - public Dictionary VolumeControls { get; private set; } - - public const int RouteOffTime = 500; - Dictionary RouteOffTimers = new Dictionary(); - - /// - /// Text that represents when an output has no source routed to it - /// - public string NoRouteText = ""; - - /// - /// Factory method to create a new chassis controller from config data. Limited to 8x8 right now - /// - public static DmChassisController GetDmChassisController(string key, string name, - string type, DMChassisPropertiesConfig properties) - { - try - { - type = type.ToLower(); - uint ipid = properties.Control.IpIdInt; - - DmMDMnxn chassis = null; - switch (type) { - case "dmmd8x8": - chassis = new DmMd8x8(ipid, Global.ControlSystem); - break; - case "dmmd8x8rps": - chassis = new DmMd8x8rps(ipid, Global.ControlSystem); - break; - case "dmmd8x8cpu3": - chassis = new DmMd8x8Cpu3(ipid, Global.ControlSystem); - break; - case "dmmd8x8cpu3rps": - chassis = new DmMd8x8Cpu3rps(ipid, Global.ControlSystem); - break; - case "dmmd16x16": - chassis = new DmMd16x16(ipid, Global.ControlSystem); - break; - case "dmmd16x16rps": - chassis = new DmMd16x16rps(ipid, Global.ControlSystem); - break; - case "dmmd16x16cpu3": - chassis = new DmMd16x16Cpu3(ipid, Global.ControlSystem); - break; - case "dmmd16x16cpu3rps": - chassis = new DmMd16x16Cpu3rps(ipid, Global.ControlSystem); - break; - case "dmmd32x32": - chassis = new DmMd32x32(ipid, Global.ControlSystem); - break; - case "dmmd32x32rps": - chassis = new DmMd32x32rps(ipid, Global.ControlSystem); - break; - case "dmmd32x32cpu3": - chassis = new DmMd32x32Cpu3(ipid, Global.ControlSystem); - break; - case "dmmd32x32cpu3rps": - chassis = new DmMd32x32Cpu3rps(ipid, Global.ControlSystem); - break; - } - - if (chassis == null) - return null; - - var controller = new DmChassisController(key, name, chassis); - + public Dictionary OutputStreamCardStateFeedbacks { get; private set; } + + public Dictionary InputCardHdcpCapabilityTypes { get; private set; } + + // Need a couple Lists of generic Backplane ports + public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection OutputPorts { get; private set; } + + public Dictionary TxDictionary { get; set; } + public Dictionary RxDictionary { get; set; } + + //public Dictionary InputCards { get; private set; } + //public Dictionary OutputCards { get; private set; } + + public Dictionary InputNames { get; set; } + public Dictionary OutputNames { get; set; } + public Dictionary VolumeControls { get; private set; } + + public const int RouteOffTime = 500; + Dictionary RouteOffTimers = new Dictionary(); + + /// + /// Text that represents when an output has no source routed to it + /// + public string NoRouteText = ""; + + /// + /// Factory method to create a new chassis controller from config data. Limited to 8x8 right now + /// + public static DmChassisController GetDmChassisController(string key, string name, + string type, DMChassisPropertiesConfig properties) + { + try + { + type = type.ToLower(); + uint ipid = properties.Control.IpIdInt; + + DmMDMnxn chassis = null; + switch (type) { + case "dmmd8x8": + chassis = new DmMd8x8(ipid, Global.ControlSystem); + break; + case "dmmd8x8rps": + chassis = new DmMd8x8rps(ipid, Global.ControlSystem); + break; + case "dmmd8x8cpu3": + chassis = new DmMd8x8Cpu3(ipid, Global.ControlSystem); + break; + case "dmmd8x8cpu3rps": + chassis = new DmMd8x8Cpu3rps(ipid, Global.ControlSystem); + break; + case "dmmd16x16": + chassis = new DmMd16x16(ipid, Global.ControlSystem); + break; + case "dmmd16x16rps": + chassis = new DmMd16x16rps(ipid, Global.ControlSystem); + break; + case "dmmd16x16cpu3": + chassis = new DmMd16x16Cpu3(ipid, Global.ControlSystem); + break; + case "dmmd16x16cpu3rps": + chassis = new DmMd16x16Cpu3rps(ipid, Global.ControlSystem); + break; + case "dmmd32x32": + chassis = new DmMd32x32(ipid, Global.ControlSystem); + break; + case "dmmd32x32rps": + chassis = new DmMd32x32rps(ipid, Global.ControlSystem); + break; + case "dmmd32x32cpu3": + chassis = new DmMd32x32Cpu3(ipid, Global.ControlSystem); + break; + case "dmmd32x32cpu3rps": + chassis = new DmMd32x32Cpu3rps(ipid, Global.ControlSystem); + break; + } + + if (chassis == null) + return null; + + var controller = new DmChassisController(key, name, chassis); + // var clearInputPort = new RoutingInputPort(NonePortKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.None, null, controller); - controller.InputPorts.Add(clearInputPort); - - // add the cards and port names - foreach (var kvp in properties.InputSlots) - controller.AddInputCard(kvp.Value, kvp.Key); - - foreach (var kvp in properties.OutputSlots) - controller.AddOutputCard(kvp.Value, kvp.Key); - - foreach (var kvp in properties.VolumeControls) - { - // get the card - // check it for an audio-compatible type - // make a something-something that will make it work - // retire to mountain village - var outNum = kvp.Key; - var card = controller.Chassis.Outputs[outNum].Card; - Audio.Output audio = null; - if (card is DmcHdo) - audio = (card as DmcHdo).Audio; - else if (card is Dmc4kHdo) - audio = (card as Dmc4kHdo).Audio; - if (audio == null) - continue; - - // wire up the audio to something here... - controller.AddVolumeControl(outNum, audio); - } - - controller.InputNames = properties.InputNames; - controller.OutputNames = properties.OutputNames; - - if (!string.IsNullOrEmpty(properties.NoRouteText)) - { - controller.NoRouteText = properties.NoRouteText; - Debug.Console(1, controller, "Setting No Route Text value to: {0}", controller.NoRouteText); - } - else - { - Debug.Console(1, controller, "NoRouteText not specified. Defaulting to blank string.", controller.NoRouteText); - } - - controller.PropertiesConfig = properties; - return controller; - } - catch (Exception e) - { - Debug.Console(0, "Error creating DM chassis:\r{0}", e); - } - - return null; - } - - /// - /// - /// - /// - /// - /// - public DmChassisController(string key, string name, DmMDMnxn chassis) - : base(key, name, chassis) + controller.InputPorts.Add(clearInputPort); + + // add the cards and port names + foreach (var kvp in properties.InputSlots) + controller.AddInputCard(kvp.Value, kvp.Key); + + foreach (var kvp in properties.OutputSlots) + controller.AddOutputCard(kvp.Value, kvp.Key); + + foreach (var kvp in properties.VolumeControls) + { + // get the card + // check it for an audio-compatible type + // make a something-something that will make it work + // retire to mountain village + var outNum = kvp.Key; + var card = controller.Chassis.Outputs[outNum].Card; + Audio.Output audio = null; + if (card is DmcHdo) + audio = (card as DmcHdo).Audio; + else if (card is Dmc4kHdo) + audio = (card as Dmc4kHdo).Audio; + if (audio == null) + continue; + + // wire up the audio to something here... + controller.AddVolumeControl(outNum, audio); + } + + controller.InputNames = properties.InputNames; + controller.OutputNames = properties.OutputNames; + + if (!string.IsNullOrEmpty(properties.NoRouteText)) + { + controller.NoRouteText = properties.NoRouteText; + Debug.Console(1, controller, "Setting No Route Text value to: {0}", controller.NoRouteText); + } + else + { + Debug.Console(1, controller, "NoRouteText not specified. Defaulting to blank string.", controller.NoRouteText); + } + + controller.PropertiesConfig = properties; + return controller; + } + catch (Exception e) + { + Debug.Console(0, "Error creating DM chassis:\r{0}", e); + } + + return null; + } + + /// + /// + /// + /// + /// + /// + public DmChassisController(string key, string name, DmMDMnxn chassis) + : base(key, name, chassis) { - - Chassis = chassis; - InputPorts = new RoutingPortCollection(); - OutputPorts = new RoutingPortCollection(); - VolumeControls = new Dictionary(); - TxDictionary = new Dictionary(); - RxDictionary = new Dictionary(); - IsOnline.OutputChange += new EventHandler(IsOnline_OutputChange); - Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange); - Chassis.DMSystemChange += new DMSystemEventHandler(Chassis_DMSystemChange); - Chassis.DMOutputChange += new DMOutputEventHandler(Chassis_DMOutputChange); - Chassis.BaseEvent += ChassisOnBaseEvent; - VideoOutputFeedbacks = new Dictionary(); - AudioOutputFeedbacks = new Dictionary(); - UsbOutputRoutedToFeebacks = new Dictionary(); - UsbInputRoutedToFeebacks = new Dictionary(); - OutputDisabledByHdcpFeedbacks = new Dictionary(); - VideoInputSyncFeedbacks = new Dictionary(); - InputNameFeedbacks = new Dictionary(); - OutputNameFeedbacks = new Dictionary(); - OutputVideoRouteNameFeedbacks = new Dictionary(); - OutputAudioRouteNameFeedbacks = new Dictionary(); - InputEndpointOnlineFeedbacks = new Dictionary(); - OutputEndpointOnlineFeedbacks = new Dictionary(); - - SystemIdFeebdack = new IntFeedback(() => { return (Chassis as DmMDMnxn).SystemIdFeedback.UShortValue; }); - SystemIdBusyFeedback = new BoolFeedback(() => { return (Chassis as DmMDMnxn).SystemIdBusy.BoolValue; }); - EnableAudioBreakawayFeedback = - new BoolFeedback(() => (Chassis as DmMDMnxn).EnableAudioBreakawayFeedback.BoolValue); - EnableUsbBreakawayFeedback = - new BoolFeedback(() => (Chassis as DmMDMnxn).EnableUSBBreakawayFeedback.BoolValue); - + + Chassis = chassis; + InputPorts = new RoutingPortCollection(); + OutputPorts = new RoutingPortCollection(); + VolumeControls = new Dictionary(); + TxDictionary = new Dictionary(); + RxDictionary = new Dictionary(); + IsOnline.OutputChange += new EventHandler(IsOnline_OutputChange); + Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange); + Chassis.DMSystemChange += new DMSystemEventHandler(Chassis_DMSystemChange); + Chassis.DMOutputChange += new DMOutputEventHandler(Chassis_DMOutputChange); + Chassis.BaseEvent += ChassisOnBaseEvent; + VideoOutputFeedbacks = new Dictionary(); + AudioOutputFeedbacks = new Dictionary(); + UsbOutputRoutedToFeebacks = new Dictionary(); + UsbInputRoutedToFeebacks = new Dictionary(); + OutputDisabledByHdcpFeedbacks = new Dictionary(); + VideoInputSyncFeedbacks = new Dictionary(); + InputNameFeedbacks = new Dictionary(); + OutputNameFeedbacks = new Dictionary(); + OutputVideoRouteNameFeedbacks = new Dictionary(); + OutputAudioRouteNameFeedbacks = new Dictionary(); + InputEndpointOnlineFeedbacks = new Dictionary(); + OutputEndpointOnlineFeedbacks = new Dictionary(); + + SystemIdFeebdack = new IntFeedback(() => { return (Chassis as DmMDMnxn).SystemIdFeedback.UShortValue; }); + SystemIdBusyFeedback = new BoolFeedback(() => { return (Chassis as DmMDMnxn).SystemIdBusy.BoolValue; }); + EnableAudioBreakawayFeedback = + new BoolFeedback(() => (Chassis as DmMDMnxn).EnableAudioBreakawayFeedback.BoolValue); + EnableUsbBreakawayFeedback = + new BoolFeedback(() => (Chassis as DmMDMnxn).EnableUSBBreakawayFeedback.BoolValue); + InputCardHdcpStateFeedbacks = new Dictionary(); InputStreamCardStateFeedbacks = new Dictionary(); - OutputStreamCardStateFeedbacks = new Dictionary(); - InputCardHdcpCapabilityTypes = new Dictionary(); - - for (uint x = 1; x <= Chassis.NumberOfOutputs; x++) - { - var tempX = x; - - if (Chassis.Outputs[tempX] != null) - { - VideoOutputFeedbacks[tempX] = new IntFeedback(() => { - if (Chassis.Outputs[tempX].VideoOutFeedback != null) - return (ushort)Chassis.Outputs[tempX].VideoOutFeedback.Number; - - return 0; - }); - AudioOutputFeedbacks[tempX] = new IntFeedback(() => { - if (Chassis.Outputs[tempX].AudioOutFeedback != null) - return (ushort)Chassis.Outputs[tempX].AudioOutFeedback.Number; - - return 0; - }); - UsbOutputRoutedToFeebacks[tempX] = new IntFeedback(() => { - if (Chassis.Outputs[tempX].USBRoutedToFeedback != null) - return (ushort)Chassis.Outputs[tempX].USBRoutedToFeedback.Number; - - return 0; - }); - - OutputNameFeedbacks[tempX] = new StringFeedback(() => { - if (Chassis.Outputs[tempX].NameFeedback != null) - return Chassis.Outputs[tempX].NameFeedback.StringValue; - - return ""; - }); - OutputVideoRouteNameFeedbacks[tempX] = new StringFeedback(() => { - if (Chassis.Outputs[tempX].VideoOutFeedback != null) - return Chassis.Outputs[tempX].VideoOutFeedback.NameFeedback.StringValue; - - return NoRouteText; - }); - OutputAudioRouteNameFeedbacks[tempX] = new StringFeedback(() => { - if (Chassis.Outputs[tempX].AudioOutFeedback != null) - return Chassis.Outputs[tempX].AudioOutFeedback.NameFeedback.StringValue; - - return NoRouteText; - }); - OutputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => Chassis.Outputs[tempX].EndpointOnlineFeedback); - - OutputDisabledByHdcpFeedbacks[tempX] = new BoolFeedback(() => { - var output = Chassis.Outputs[tempX]; - - var hdmiTxOutput = output as Card.HdmiTx; - if (hdmiTxOutput != null) - return hdmiTxOutput.HdmiOutput.DisabledByHdcp.BoolValue; - - var dmHdmiOutput = output as Card.DmHdmiOutput; - if (dmHdmiOutput != null) - return dmHdmiOutput.DisabledByHdcpFeedback.BoolValue; - - var dmsDmOutAdvanced = output as Card.DmsDmOutAdvanced; - if (dmsDmOutAdvanced != null) - return dmsDmOutAdvanced.DisabledByHdcpFeedback.BoolValue; - - var dmps3HdmiAudioOutput = output as Card.Dmps3HdmiAudioOutput; - if (dmps3HdmiAudioOutput != null) - return dmps3HdmiAudioOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; - - var dmps3HdmiOutput = output as Card.Dmps3HdmiOutput; - if (dmps3HdmiOutput != null) - return dmps3HdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; - - var dmps3HdmiOutputBackend = output as Card.Dmps3HdmiOutputBackend; - if (dmps3HdmiOutputBackend != null) - return dmps3HdmiOutputBackend.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; - - // var hdRx4kX10HdmiOutput = output as HdRx4kX10HdmiOutput; - // if (hdRx4kX10HdmiOutput != null) - // return hdRx4kX10HdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; - - // var hdMdNxMHdmiOutput = output as HdMdNxMHdmiOutput; - // if (hdMdNxMHdmiOutput != null) - // return hdMdNxMHdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; - - return false; + OutputStreamCardStateFeedbacks = new Dictionary(); + InputCardHdcpCapabilityTypes = new Dictionary(); + + for (uint x = 1; x <= Chassis.NumberOfOutputs; x++) + { + var tempX = x; + + if (Chassis.Outputs[tempX] != null) + { + VideoOutputFeedbacks[tempX] = new IntFeedback(() => { + if (Chassis.Outputs[tempX].VideoOutFeedback != null) + return (ushort)Chassis.Outputs[tempX].VideoOutFeedback.Number; + + return 0; + }); + AudioOutputFeedbacks[tempX] = new IntFeedback(() => { + if (Chassis.Outputs[tempX].AudioOutFeedback != null) + return (ushort)Chassis.Outputs[tempX].AudioOutFeedback.Number; + + return 0; + }); + UsbOutputRoutedToFeebacks[tempX] = new IntFeedback(() => { + if (Chassis.Outputs[tempX].USBRoutedToFeedback != null) + return (ushort)Chassis.Outputs[tempX].USBRoutedToFeedback.Number; + + return 0; + }); + + OutputNameFeedbacks[tempX] = new StringFeedback(() => { + if (Chassis.Outputs[tempX].NameFeedback != null) + return Chassis.Outputs[tempX].NameFeedback.StringValue; + + return ""; + }); + OutputVideoRouteNameFeedbacks[tempX] = new StringFeedback(() => { + if (Chassis.Outputs[tempX].VideoOutFeedback != null) + return Chassis.Outputs[tempX].VideoOutFeedback.NameFeedback.StringValue; + + return NoRouteText; + }); + OutputAudioRouteNameFeedbacks[tempX] = new StringFeedback(() => { + if (Chassis.Outputs[tempX].AudioOutFeedback != null) + return Chassis.Outputs[tempX].AudioOutFeedback.NameFeedback.StringValue; + + return NoRouteText; + }); + OutputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => Chassis.Outputs[tempX].EndpointOnlineFeedback); + + OutputDisabledByHdcpFeedbacks[tempX] = new BoolFeedback(() => { + var output = Chassis.Outputs[tempX]; + + var hdmiTxOutput = output as Card.HdmiTx; + if (hdmiTxOutput != null) + return hdmiTxOutput.HdmiOutput.DisabledByHdcp.BoolValue; + + var dmHdmiOutput = output as Card.DmHdmiOutput; + if (dmHdmiOutput != null) + return dmHdmiOutput.DisabledByHdcpFeedback.BoolValue; + + var dmsDmOutAdvanced = output as Card.DmsDmOutAdvanced; + if (dmsDmOutAdvanced != null) + return dmsDmOutAdvanced.DisabledByHdcpFeedback.BoolValue; + + var dmps3HdmiAudioOutput = output as Card.Dmps3HdmiAudioOutput; + if (dmps3HdmiAudioOutput != null) + return dmps3HdmiAudioOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + var dmps3HdmiOutput = output as Card.Dmps3HdmiOutput; + if (dmps3HdmiOutput != null) + return dmps3HdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + var dmps3HdmiOutputBackend = output as Card.Dmps3HdmiOutputBackend; + if (dmps3HdmiOutputBackend != null) + return dmps3HdmiOutputBackend.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + // var hdRx4kX10HdmiOutput = output as HdRx4kX10HdmiOutput; + // if (hdRx4kX10HdmiOutput != null) + // return hdRx4kX10HdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + // var hdMdNxMHdmiOutput = output as HdMdNxMHdmiOutput; + // if (hdMdNxMHdmiOutput != null) + // return hdMdNxMHdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + return false; }); OutputStreamCardStateFeedbacks[tempX] = new IntFeedback(() => { @@ -346,105 +346,105 @@ namespace PepperDash.Essentials.DM Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "Error adding output stream card in slot: {0}. Error: {1}", tempX, iopex); return 0; } - }); - } - - if (Chassis.Inputs[tempX] != null) - { - UsbInputRoutedToFeebacks[tempX] = new IntFeedback(() => { - if (Chassis.Inputs[tempX].USBRoutedToFeedback != null) - return (ushort)Chassis.Inputs[tempX].USBRoutedToFeedback.Number; - - return 0; - }); - VideoInputSyncFeedbacks[tempX] = new BoolFeedback(() => { - if (Chassis.Inputs[tempX].VideoDetectedFeedback != null) - return Chassis.Inputs[tempX].VideoDetectedFeedback.BoolValue; - - return false; - }); - InputNameFeedbacks[tempX] = new StringFeedback(() => { - if (Chassis.Inputs[tempX].NameFeedback != null) - return Chassis.Inputs[tempX].NameFeedback.StringValue; - - return ""; - }); - - InputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => { return Chassis.Inputs[tempX].EndpointOnlineFeedback; }); - - InputCardHdcpStateFeedbacks[tempX] = new IntFeedback(() => { - try - { - var inputCard = Chassis.Inputs[tempX]; - - if (inputCard.Card is DmcHd) - { - InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; - - if ((inputCard.Card as DmcHd).HdmiInput.HdcpSupportOnFeedback.BoolValue) - return 1; - return 0; - } - - if (inputCard.Card is DmcHdDsp) - { - InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; - - if ((inputCard.Card as DmcHdDsp).HdmiInput.HdcpSupportOnFeedback.BoolValue) - return 1; - return 0; - } - if (inputCard.Card is Dmc4kHdBase) - { - InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support; - return (int)(inputCard.Card as Dmc4kHdBase).HdmiInput.HdcpReceiveCapability; - } - if (inputCard.Card is Dmc4kHdDspBase) - { - if (PropertiesConfig.InputSlotSupportsHdcp2[tempX]) - { - InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support; - return (int)(inputCard.Card as Dmc4kHdDspBase).HdmiInput.HdcpReceiveCapability; - } - - InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; - if ((inputCard.Card as Dmc4kHdDspBase).HdmiInput.HdcpSupportOnFeedback.BoolValue) - return 1; - return 0; - } - - if (inputCard.Card is Dmc4kCBase) - { - if (PropertiesConfig.InputSlotSupportsHdcp2[tempX]) - { - InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; - return (int)(inputCard.Card as Dmc4kCBase).DmInput.HdcpReceiveCapability; - } - - if ((inputCard.Card as Dmc4kCBase).DmInput.HdcpSupportOnFeedback.BoolValue) - return 1; - return 0; - } - if (inputCard.Card is Dmc4kCDspBase) - { - if (PropertiesConfig.InputSlotSupportsHdcp2[tempX]) - { - InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; - return (int)(inputCard.Card as Dmc4kCDspBase).DmInput.HdcpReceiveCapability; - } - - if ((inputCard.Card as Dmc4kCDspBase).DmInput.HdcpSupportOnFeedback.BoolValue) - return 1; - - return 0; - } - return 0; - } - catch (InvalidOperationException iopex) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "The Input Card in slot: {0} supports HDCP 2. Please update the configuration value in the inputCardSupportsHdcp2 object to true. Error: {1}", tempX, iopex); - return 0; - } + }); + } + + if (Chassis.Inputs[tempX] != null) + { + UsbInputRoutedToFeebacks[tempX] = new IntFeedback(() => { + if (Chassis.Inputs[tempX].USBRoutedToFeedback != null) + return (ushort)Chassis.Inputs[tempX].USBRoutedToFeedback.Number; + + return 0; + }); + VideoInputSyncFeedbacks[tempX] = new BoolFeedback(() => { + if (Chassis.Inputs[tempX].VideoDetectedFeedback != null) + return Chassis.Inputs[tempX].VideoDetectedFeedback.BoolValue; + + return false; + }); + InputNameFeedbacks[tempX] = new StringFeedback(() => { + if (Chassis.Inputs[tempX].NameFeedback != null) + return Chassis.Inputs[tempX].NameFeedback.StringValue; + + return ""; + }); + + InputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => { return Chassis.Inputs[tempX].EndpointOnlineFeedback; }); + + InputCardHdcpStateFeedbacks[tempX] = new IntFeedback(() => { + try + { + var inputCard = Chassis.Inputs[tempX]; + + if (inputCard.Card is DmcHd) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; + + if ((inputCard.Card as DmcHd).HdmiInput.HdcpSupportOnFeedback.BoolValue) + return 1; + return 0; + } + + if (inputCard.Card is DmcHdDsp) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; + + if ((inputCard.Card as DmcHdDsp).HdmiInput.HdcpSupportOnFeedback.BoolValue) + return 1; + return 0; + } + if (inputCard.Card is Dmc4kHdBase) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support; + return (int)(inputCard.Card as Dmc4kHdBase).HdmiInput.HdcpReceiveCapability; + } + if (inputCard.Card is Dmc4kHdDspBase) + { + if (PropertiesConfig.InputSlotSupportsHdcp2[tempX]) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support; + return (int)(inputCard.Card as Dmc4kHdDspBase).HdmiInput.HdcpReceiveCapability; + } + + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; + if ((inputCard.Card as Dmc4kHdDspBase).HdmiInput.HdcpSupportOnFeedback.BoolValue) + return 1; + return 0; + } + + if (inputCard.Card is Dmc4kCBase) + { + if (PropertiesConfig.InputSlotSupportsHdcp2[tempX]) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; + return (int)(inputCard.Card as Dmc4kCBase).DmInput.HdcpReceiveCapability; + } + + if ((inputCard.Card as Dmc4kCBase).DmInput.HdcpSupportOnFeedback.BoolValue) + return 1; + return 0; + } + if (inputCard.Card is Dmc4kCDspBase) + { + if (PropertiesConfig.InputSlotSupportsHdcp2[tempX]) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; + return (int)(inputCard.Card as Dmc4kCDspBase).DmInput.HdcpReceiveCapability; + } + + if ((inputCard.Card as Dmc4kCDspBase).DmInput.HdcpSupportOnFeedback.BoolValue) + return 1; + + return 0; + } + return 0; + } + catch (InvalidOperationException iopex) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "The Input Card in slot: {0} supports HDCP 2. Please update the configuration value in the inputCardSupportsHdcp2 object to true. Error: {1}", tempX, iopex); + return 0; + } }); InputStreamCardStateFeedbacks[tempX] = new IntFeedback(() => { @@ -472,111 +472,111 @@ namespace PepperDash.Essentials.DM Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "Error adding input stream card in slot: {0}. Error: {1}", tempX, iopex); return 0; } - }); - } - } - } - - private void ChassisOnBaseEvent(GenericBase device, BaseEventArgs args) - { - - } - - /// - /// - /// - /// - /// - public void AddInputCard(string type, uint number) - { - Debug.Console(2, this, "Adding input card '{0}', slot {1}", type, number); - - type = type.ToLower(); - + }); + } + } + } + + private void ChassisOnBaseEvent(GenericBase device, BaseEventArgs args) + { + + } + + /// + /// + /// + /// + /// + public void AddInputCard(string type, uint number) + { + Debug.Console(2, this, "Adding input card '{0}', slot {1}", type, number); + + type = type.ToLower(); + switch (type) { case "dmchd": - { - var inputCard = new DmcHd(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + { + var inputCard = new DmcHd(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); } break; case "dmchddsp": - { - var inputCard = new DmcHdDsp(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + { + var inputCard = new DmcHdDsp(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); } break; case "dmc4khd": - { - var inputCard = new Dmc4kHd(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + { + var inputCard = new Dmc4kHd(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); } break; case "dmc4khddsp": - { - var inputCard = new Dmc4kHdDsp(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + { + var inputCard = new Dmc4kHdDsp(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); } break; case "dmc4kzhd": - { - var inputCard = new Dmc4kzHd(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + { + var inputCard = new Dmc4kzHd(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); } break; case "dmc4kzhddsp": - { - var inputCard = new Dmc4kzHdDsp(number, this.Chassis); - var cecPort = inputCard.HdmiInput as ICec; - AddHdmiInCardPorts(number, cecPort); + { + var inputCard = new Dmc4kzHdDsp(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); } break; case "dmcc": - { - var inputCard = new DmcC(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); + { + var inputCard = new DmcC(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); } break; case "dmccdsp": - { - var inputCard = new DmcCDsp(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); + { + var inputCard = new DmcCDsp(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); } break; case "dmc4kc": - { - var inputCard = new Dmc4kC(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); + { + var inputCard = new Dmc4kC(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); } break; case "dmc4kcdsp": - { - var inputCard = new Dmc4kCDsp(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); + { + var inputCard = new Dmc4kCDsp(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); } break; case "dmc4kzc": - { - var inputCard = new Dmc4kzC(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); + { + var inputCard = new Dmc4kzC(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); } break; case "dmc4kzcdsp": - { - var inputCard = new Dmc4kzCDsp(number, this.Chassis); - var cecPort = inputCard.DmInput as ICec; - AddDmInCardPorts(number, cecPort); + { + var inputCard = new Dmc4kzCDsp(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); } break; case "dmccat": @@ -610,7 +610,7 @@ namespace PepperDash.Essentials.DM case "dmcsdi": new DmcSdi(number, Chassis); AddInputPortWithDebug(number, "sdiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Sdi); - AddOutputPortWithDebug(string.Format("inputCard{0}", number), "sdiOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, + AddOutputPortWithDebug(string.Format("inputCard{0}", number), "sdiOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Sdi, null); AddInCardHdmiAndAudioLoopPorts(number); break; @@ -657,324 +657,324 @@ namespace PepperDash.Essentials.DM AddInputPortWithDebug(number, "streamIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming); AddInCardHdmiAndAudioLoopPorts(number); break; - } - } - - void AddDmInCardPorts(uint number) - { - AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat); - AddInCardHdmiAndAudioLoopPorts(number); - } - - void AddDmInCardPorts(uint number, ICec cecPort) - { - AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort); - AddInCardHdmiAndAudioLoopPorts(number); - } - - void AddHdmiInCardPorts(uint number, ICec cecPort) - { - AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort); - AddInCardHdmiAndAudioLoopPorts(number); - } - - void AddInCardHdmiAndAudioLoopPorts(uint number) - { - AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null); - AddOutputPortWithDebug(string.Format("inputCard{0}", number), "audioLoopOut", eRoutingSignalType.Audio, eRoutingPortConnectionType.Hdmi, null); - } - - void AddInCardHdmiLoopPort(uint number) - { - AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null); - } - - /// - /// - /// - /// - /// - public void AddOutputCard(string type, uint number) - { - type = type.ToLower(); - - Debug.Console(2, this, "Adding output card '{0}', slot {1}", type, number); + } + } + + void AddDmInCardPorts(uint number) + { + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat); + AddInCardHdmiAndAudioLoopPorts(number); + } + + void AddDmInCardPorts(uint number, ICec cecPort) + { + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort); + AddInCardHdmiAndAudioLoopPorts(number); + } + + void AddHdmiInCardPorts(uint number, ICec cecPort) + { + AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort); + AddInCardHdmiAndAudioLoopPorts(number); + } + + void AddInCardHdmiAndAudioLoopPorts(uint number) + { + AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null); + AddOutputPortWithDebug(string.Format("inputCard{0}", number), "audioLoopOut", eRoutingSignalType.Audio, eRoutingPortConnectionType.Hdmi, null); + } + + void AddInCardHdmiLoopPort(uint number) + { + AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null); + } + + /// + /// + /// + /// + /// + public void AddOutputCard(string type, uint number) + { + type = type.ToLower(); + + Debug.Console(2, this, "Adding output card '{0}', slot {1}", type, number); switch (type) { case "dmc4khdo": - { - var outputCard = new Dmc4kHdoSingle(number, Chassis); - var cecPort1 = outputCard.Card1.HdmiOutput; - var cecPort2 = outputCard.Card2.HdmiOutput; - AddDmcHdoPorts(number, cecPort1, cecPort2); + { + var outputCard = new Dmc4kHdoSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + var cecPort2 = outputCard.Card2.HdmiOutput; + AddDmcHdoPorts(number, cecPort1, cecPort2); } break; case "dmc4kzhdo": - { - var outputCard = new Dmc4kzHdoSingle(number, Chassis); - var cecPort1 = outputCard.Card1.HdmiOutput; - var cecPort2 = outputCard.Card2.HdmiOutput; - AddDmcHdoPorts(number, cecPort1, cecPort2); + { + var outputCard = new Dmc4kzHdoSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + var cecPort2 = outputCard.Card2.HdmiOutput; + AddDmcHdoPorts(number, cecPort1, cecPort2); } break; case "dmchdo": - { - var outputCard = new DmcHdoSingle(number, Chassis); - var cecPort1 = outputCard.Card1.HdmiOutput; - var cecPort2 = outputCard.Card2.HdmiOutput; - AddDmcHdoPorts(number, cecPort1, cecPort2); + { + var outputCard = new DmcHdoSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + var cecPort2 = outputCard.Card2.HdmiOutput; + AddDmcHdoPorts(number, cecPort1, cecPort2); } break; case "dmc4kcohd": - { - var outputCard = new Dmc4kCoHdSingle(number, Chassis); - var cecPort1 = outputCard.Card1.HdmiOutput; - AddDmcCoPorts(number, cecPort1); + { + var outputCard = new Dmc4kCoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddDmcCoPorts(number, cecPort1); } break; case "dmc4kzcohd": - { - var outputCard = new Dmc4kzCoHdSingle(number, Chassis); - var cecPort1 = outputCard.Card1.HdmiOutput; - AddDmcCoPorts(number, cecPort1); + { + var outputCard = new Dmc4kzCoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddDmcCoPorts(number, cecPort1); } break; case "dmccohd": - { - var outputCard = new DmcCoHdSingle(number, Chassis); - var cecPort1 = outputCard.Card1.HdmiOutput; - AddDmcCoPorts(number, cecPort1); + { + var outputCard = new DmcCoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddDmcCoPorts(number, cecPort1); } break; case "dmccatohd": - { - var outputCard = new DmcCatoHdSingle(number, Chassis); - var cecPort1 = outputCard.Card1.HdmiOutput; - AddDmcCoPorts(number, cecPort1); + { + var outputCard = new DmcCatoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddDmcCoPorts(number, cecPort1); } break; case "dmcsohd": - { - var outputCard = new DmcSoHdSingle(number, Chassis); - var cecPort1 = outputCard.Card1.HdmiOutput; - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.DmMmFiber, Chassis.Outputs[2 * (number - 1) + 1]); - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 1], cecPort1); - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.DmMmFiber, Chassis.Outputs[2 * (number - 1) + 2]); + { + var outputCard = new DmcSoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmMmFiber, Chassis.Outputs[2 * (number - 1) + 1]); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 1], cecPort1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmMmFiber, Chassis.Outputs[2 * (number - 1) + 2]); } break; case "dmcs2ohd": - { - var outputCard = new DmcS2oHdSingle(number, Chassis); - var cecPort1 = outputCard.Card1.HdmiOutput; - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.DmSmFiber, Chassis.Outputs[2 * (number - 1) + 1]); - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 1], cecPort1); - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.DmSmFiber, Chassis.Outputs[2 * (number - 1) + 2]); + { + var outputCard = new DmcS2oHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmSmFiber, Chassis.Outputs[2 * (number - 1) + 1]); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 1], cecPort1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmSmFiber, Chassis.Outputs[2 * (number - 1) + 2]); } break; case "dmcstro": - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "streamOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "streamOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming, Chassis.Outputs[2 * (number - 1) + 1]); break; default: Debug.Console(1, this, " WARNING: Output card type '{0}' is not available", type); break; - } - } - - void AddDmcHdoPorts(uint number, ICec cecPort1, ICec cecPort2) - { - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 1], cecPort1); - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "audioOut1", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio, - Chassis.Outputs[2 * (number - 1) + 1]); - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 2], cecPort2); - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "audioOut2", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio, - Chassis.Outputs[2 * (number - 1) + 2]); - } - - void AddDmcCoPorts(uint number, ICec cecPort1) - { - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.DmCat, Chassis.Outputs[2 * (number - 1) + 1]); - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 1], cecPort1); - AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.DmCat, Chassis.Outputs[2 * (number - 1) + 2]); - } - - /// - /// Adds InputPort - /// + } + } + + void AddDmcHdoPorts(uint number, ICec cecPort1, ICec cecPort2) + { + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 1], cecPort1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "audioOut1", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio, + Chassis.Outputs[2 * (number - 1) + 1]); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 2], cecPort2); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "audioOut2", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio, + Chassis.Outputs[2 * (number - 1) + 2]); + } + + void AddDmcCoPorts(uint number, ICec cecPort1) + { + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmCat, Chassis.Outputs[2 * (number - 1) + 1]); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, Chassis.Outputs[2 * (number - 1) + 1], cecPort1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmCat, Chassis.Outputs[2 * (number - 1) + 2]); + } + + /// + /// Adds InputPort + /// void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType) { AddInputPortWithDebug(cardNum, portName, sigType, portType, null); - } - - /// - /// Adds InputPort and sets Port as ICec object - /// - void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort) - { - var portKey = string.Format("inputCard{0}--{1}", cardNum, portName); - Debug.Console(2, this, "Adding input port '{0}'", portKey); + } + + /// + /// Adds InputPort and sets Port as ICec object + /// + void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort) + { + var portKey = string.Format("inputCard{0}--{1}", cardNum, portName); + Debug.Console(2, this, "Adding input port '{0}'", portKey); var inputPort = new RoutingInputPort(portKey, sigType, portType, Chassis.Inputs[cardNum], this) { FeedbackMatchObject = Chassis.Inputs[cardNum] - }; ; - - if (cecPort != null) - inputPort.Port = cecPort; - + }; ; + + if (cecPort != null) + inputPort.Port = cecPort; + InputPorts.Add(inputPort); - } - - /// - /// Adds OutputPort - /// + } + + /// + /// Adds OutputPort + /// void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector) { AddOutputPortWithDebug(cardName, portName, sigType, portType, selector, null); - } - - /// - /// Adds OutputPort and sets Port as ICec object - /// - void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector, ICec cecPort) - { - var portKey = string.Format("{0}--{1}", cardName, portName); + } + + /// + /// Adds OutputPort and sets Port as ICec object + /// + void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector, ICec cecPort) + { + var portKey = string.Format("{0}--{1}", cardName, portName); Debug.Console(2, this, "Adding output port '{0}'", portKey); var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this); if (portName.IndexOf("Loop", StringComparison.InvariantCultureIgnoreCase) < 0) { outputPort.FeedbackMatchObject = selector; - } - if (cecPort != null) - outputPort.Port = cecPort; - + } + if (cecPort != null) + outputPort.Port = cecPort; + OutputPorts.Add(outputPort); - } - - /// - /// - /// - void AddVolumeControl(uint number, Audio.Output audio) - { - VolumeControls.Add(number, new DmCardAudioOutputController(audio)); - } - - //public void SetInputHdcpSupport(uint input, ePdtHdcpSupport hdcpSetting) - //{ - - //} - - void Chassis_DMSystemChange(Switch device, DMSystemEventArgs args) - { - switch (args.EventId) - { - case DMSystemEventIds.SystemIdEventId: - { - Debug.Console(2, this, "SystemIdEvent Value: {0}", (Chassis as DmMDMnxn).SystemIdFeedback.UShortValue); - SystemIdFeebdack.FireUpdate(); - break; - } - case DMSystemEventIds.SystemIdBusyEventId: - { - Debug.Console(2, this, "SystemIdBusyEvent State: {0}", (Chassis as DmMDMnxn).SystemIdBusy.BoolValue); - SystemIdBusyFeedback.FireUpdate(); - break; - } - case DMSystemEventIds.AudioBreakawayEventId: - { - Debug.Console(2, this, "AudioBreakaway Event: value: {0}", - (Chassis as DmMDMnxn).EnableAudioBreakawayFeedback.BoolValue); - EnableAudioBreakawayFeedback.FireUpdate(); - break; - } - case DMSystemEventIds.USBBreakawayEventId: - { - Debug.Console(2, this, "USBBreakaway Event: value: {0}", - (Chassis as DmMDMnxn).EnableUSBBreakawayFeedback.BoolValue); - EnableUsbBreakawayFeedback.FireUpdate(); - break; - } - } - } - - void Chassis_DMInputChange(Switch device, DMInputEventArgs args) - { - try - { - switch (args.EventId) - { - case DMInputEventIds.EndpointOnlineEventId: - { - Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); - InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); - break; - } - case DMInputEventIds.OnlineFeedbackEventId: - { - Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); - InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); - break; - } - case DMInputEventIds.VideoDetectedEventId: - { - Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number); - VideoInputSyncFeedbacks[args.Number].FireUpdate(); - break; - } - case DMInputEventIds.InputNameEventId: - { - Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number); - InputNameFeedbacks[args.Number].FireUpdate(); - break; - } - case DMInputEventIds.UsbRoutedToEventId: - { - Debug.Console(2, this, "DM Input {0} UsbRoutedToEventId", args.Number); - if (UsbInputRoutedToFeebacks[args.Number] != null) - UsbInputRoutedToFeebacks[args.Number].FireUpdate(); - else - Debug.Console(1, this, "No index of {0} found in UsbInputRoutedToFeedbacks"); - break; - } - case DMInputEventIds.HdcpCapabilityFeedbackEventId: - { - Debug.Console(2, this, "DM Input {0} HdcpCapabilityFeedbackEventId", args.Number); - if (InputCardHdcpStateFeedbacks[args.Number] != null) - InputCardHdcpStateFeedbacks[args.Number].FireUpdate(); - else - Debug.Console(1, this, "No index of {0} found in InputCardHdcpCapabilityFeedbacks"); - break; - } - case DMInputEventIds.HdcpSupportOffEventId: - { - Debug.Console(2, this, "DM Input {0} HdcpSupportOffEventId", args.Number); - if (InputCardHdcpStateFeedbacks[args.Number] != null) - InputCardHdcpStateFeedbacks[args.Number].FireUpdate(); - else - Debug.Console(1, this, "No index of {0} found in InputCardHdcpCapabilityFeedbacks"); - break; - } - case DMInputEventIds.HdcpSupportOnEventId: - { - Debug.Console(2, this, "DM Input {0} HdcpSupportOnEventId", args.Number); - if (InputCardHdcpStateFeedbacks[args.Number] != null) - InputCardHdcpStateFeedbacks[args.Number].FireUpdate(); - else - Debug.Console(1, this, "No index of {0} found in InputCardHdcpCapabilityFeedbacks"); - break; + } + + /// + /// + /// + void AddVolumeControl(uint number, Audio.Output audio) + { + VolumeControls.Add(number, new DmCardAudioOutputController(audio)); + } + + //public void SetInputHdcpSupport(uint input, ePdtHdcpSupport hdcpSetting) + //{ + + //} + + void Chassis_DMSystemChange(Switch device, DMSystemEventArgs args) + { + switch (args.EventId) + { + case DMSystemEventIds.SystemIdEventId: + { + Debug.Console(2, this, "SystemIdEvent Value: {0}", (Chassis as DmMDMnxn).SystemIdFeedback.UShortValue); + SystemIdFeebdack.FireUpdate(); + break; + } + case DMSystemEventIds.SystemIdBusyEventId: + { + Debug.Console(2, this, "SystemIdBusyEvent State: {0}", (Chassis as DmMDMnxn).SystemIdBusy.BoolValue); + SystemIdBusyFeedback.FireUpdate(); + break; + } + case DMSystemEventIds.AudioBreakawayEventId: + { + Debug.Console(2, this, "AudioBreakaway Event: value: {0}", + (Chassis as DmMDMnxn).EnableAudioBreakawayFeedback.BoolValue); + EnableAudioBreakawayFeedback.FireUpdate(); + break; + } + case DMSystemEventIds.USBBreakawayEventId: + { + Debug.Console(2, this, "USBBreakaway Event: value: {0}", + (Chassis as DmMDMnxn).EnableUSBBreakawayFeedback.BoolValue); + EnableUsbBreakawayFeedback.FireUpdate(); + break; + } + } + } + + void Chassis_DMInputChange(Switch device, DMInputEventArgs args) + { + try + { + switch (args.EventId) + { + case DMInputEventIds.EndpointOnlineEventId: + { + Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); + InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); + break; + } + case DMInputEventIds.OnlineFeedbackEventId: + { + Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); + InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); + break; + } + case DMInputEventIds.VideoDetectedEventId: + { + Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number); + VideoInputSyncFeedbacks[args.Number].FireUpdate(); + break; + } + case DMInputEventIds.InputNameEventId: + { + Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number); + InputNameFeedbacks[args.Number].FireUpdate(); + break; + } + case DMInputEventIds.UsbRoutedToEventId: + { + Debug.Console(2, this, "DM Input {0} UsbRoutedToEventId", args.Number); + if (UsbInputRoutedToFeebacks[args.Number] != null) + UsbInputRoutedToFeebacks[args.Number].FireUpdate(); + else + Debug.Console(1, this, "No index of {0} found in UsbInputRoutedToFeedbacks"); + break; + } + case DMInputEventIds.HdcpCapabilityFeedbackEventId: + { + Debug.Console(2, this, "DM Input {0} HdcpCapabilityFeedbackEventId", args.Number); + if (InputCardHdcpStateFeedbacks[args.Number] != null) + InputCardHdcpStateFeedbacks[args.Number].FireUpdate(); + else + Debug.Console(1, this, "No index of {0} found in InputCardHdcpCapabilityFeedbacks"); + break; + } + case DMInputEventIds.HdcpSupportOffEventId: + { + Debug.Console(2, this, "DM Input {0} HdcpSupportOffEventId", args.Number); + if (InputCardHdcpStateFeedbacks[args.Number] != null) + InputCardHdcpStateFeedbacks[args.Number].FireUpdate(); + else + Debug.Console(1, this, "No index of {0} found in InputCardHdcpCapabilityFeedbacks"); + break; + } + case DMInputEventIds.HdcpSupportOnEventId: + { + Debug.Console(2, this, "DM Input {0} HdcpSupportOnEventId", args.Number); + if (InputCardHdcpStateFeedbacks[args.Number] != null) + InputCardHdcpStateFeedbacks[args.Number].FireUpdate(); + else + Debug.Console(1, this, "No index of {0} found in InputCardHdcpCapabilityFeedbacks"); + break; } case DMInputEventIds.StartEventId: case DMInputEventIds.StopEventId: @@ -988,18 +988,18 @@ namespace PepperDash.Essentials.DM else Debug.Console(2, this, "No index of {0} found in InputStreamCardStateFeedbacks"); break; - } - default: - { - Debug.Console(2, this, "DMInputChange fired for Input {0} with Unhandled EventId: {1}", args.Number, args.EventId); - break; - } - } - } - catch (Exception ex) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Chassis_DMInputChange: {0}", ex); - } + } + default: + { + Debug.Console(2, this, "DMInputChange fired for Input {0} with Unhandled EventId: {1}", args.Number, args.EventId); + break; + } + } + } + catch (Exception ex) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Chassis_DMInputChange: {0}", ex); + } } /// @@ -1011,42 +1011,42 @@ namespace PepperDash.Essentials.DM { var newEvent = NumericSwitchChange; if (newEvent != null) newEvent(this, e); - } - - /// - /// - void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args) - { - var output = args.Number; - - switch (args.EventId) - { - case DMOutputEventIds.VolumeEventId: - { - if (VolumeControls.ContainsKey(output)) - { - VolumeControls[args.Number].VolumeEventFromChassis(); - } - - break; - } - case DMOutputEventIds.EndpointOnlineEventId: - { - Debug.Console(2, this, "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. State: {1}", args.Number, - Chassis.Outputs[output].EndpointOnlineFeedback); - OutputEndpointOnlineFeedbacks[output].FireUpdate(); - break; - } - case DMOutputEventIds.OnlineFeedbackEventId: - { - Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}", args.Number, - Chassis.Outputs[output].EndpointOnlineFeedback); - OutputEndpointOnlineFeedbacks[output].FireUpdate(); - break; - } + } + + /// + /// + void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args) + { + var output = args.Number; + + switch (args.EventId) + { + case DMOutputEventIds.VolumeEventId: + { + if (VolumeControls.ContainsKey(output)) + { + VolumeControls[args.Number].VolumeEventFromChassis(); + } + + break; + } + case DMOutputEventIds.EndpointOnlineEventId: + { + Debug.Console(2, this, "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. State: {1}", args.Number, + Chassis.Outputs[output].EndpointOnlineFeedback); + OutputEndpointOnlineFeedbacks[output].FireUpdate(); + break; + } + case DMOutputEventIds.OnlineFeedbackEventId: + { + Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}", args.Number, + Chassis.Outputs[output].EndpointOnlineFeedback); + OutputEndpointOnlineFeedbacks[output].FireUpdate(); + break; + } case DMOutputEventIds.VideoOutEventId: - { - + { + var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis. Outputs[output].VideoOutFeedback.Number; @@ -1067,11 +1067,11 @@ namespace PepperDash.Essentials.DM eRoutingSignalType.Video)); } - if (OutputVideoRouteNameFeedbacks.ContainsKey(output)) - OutputVideoRouteNameFeedbacks[output].FireUpdate(); - - break; - } + if (OutputVideoRouteNameFeedbacks.ContainsKey(output)) + OutputVideoRouteNameFeedbacks[output].FireUpdate(); + + break; + } case DMOutputEventIds.AudioOutEventId: { var inputNumber = Chassis.Outputs[output].AudioOutFeedback == null ? 0 : Chassis. @@ -1097,25 +1097,25 @@ namespace PepperDash.Essentials.DM if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) OutputAudioRouteNameFeedbacks[output].FireUpdate(); - break; - } - case DMOutputEventIds.OutputNameEventId: - { - Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); - OutputNameFeedbacks[output].FireUpdate(); - break; - } - case DMOutputEventIds.UsbRoutedToEventId: - { - Debug.Console(2, this, "DM Output {0} UsbRoutedToEventId", args.Number); - UsbOutputRoutedToFeebacks[args.Number].FireUpdate(); - break; - } - case DMOutputEventIds.DisabledByHdcpEventId: - { - Debug.Console(2, this, "DM Output {0} DisabledByHdcpEventId", args.Number); - OutputDisabledByHdcpFeedbacks[args.Number].FireUpdate(); - break; + break; + } + case DMOutputEventIds.OutputNameEventId: + { + Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); + OutputNameFeedbacks[output].FireUpdate(); + break; + } + case DMOutputEventIds.UsbRoutedToEventId: + { + Debug.Console(2, this, "DM Output {0} UsbRoutedToEventId", args.Number); + UsbOutputRoutedToFeebacks[args.Number].FireUpdate(); + break; + } + case DMOutputEventIds.DisabledByHdcpEventId: + { + Debug.Console(2, this, "DM Output {0} DisabledByHdcpEventId", args.Number); + OutputDisabledByHdcpFeedbacks[args.Number].FireUpdate(); + break; } case DMOutputEventIds.StartEventId: case DMOutputEventIds.StopEventId: @@ -1129,50 +1129,50 @@ namespace PepperDash.Essentials.DM else Debug.Console(2, this, "No index of {0} found in OutputStreamCardStateFeedbacks"); break; - } - default: - { - Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}", args.Number, args.EventId); - break; - } - } - } - - /// - /// - /// - /// - void StartOffTimer(PortNumberType pnt) - { - if (RouteOffTimers.ContainsKey(pnt)) - return; - RouteOffTimers[pnt] = new CTimer(o => ExecuteSwitch(null, pnt.Selector, pnt.Type), RouteOffTime); - } - - // Send out sigs when coming online - void IsOnline_OutputChange(object sender, EventArgs e) - { - if (IsOnline.BoolValue) - { - (Chassis as DmMDMnxn).EnableAudioBreakaway.BoolValue = true; - (Chassis as DmMDMnxn).EnableUSBBreakaway.BoolValue = true; - - - EnableAudioBreakawayFeedback.FireUpdate(); - EnableUsbBreakawayFeedback.FireUpdate(); - - if (InputNames != null) - foreach (var kvp in InputNames) - Chassis.Inputs[kvp.Key].Name.StringValue = kvp.Value; - if (OutputNames != null) - foreach (var kvp in OutputNames) - Chassis.Outputs[kvp.Key].Name.StringValue = kvp.Value; - } - } - - #region IRouting Members - public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType) - { + } + default: + { + Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}", args.Number, args.EventId); + break; + } + } + } + + /// + /// + /// + /// + void StartOffTimer(PortNumberType pnt) + { + if (RouteOffTimers.ContainsKey(pnt)) + return; + RouteOffTimers[pnt] = new CTimer(o => ExecuteSwitch(null, pnt.Selector, pnt.Type), RouteOffTime); + } + + // Send out sigs when coming online + void IsOnline_OutputChange(object sender, EventArgs e) + { + if (IsOnline.BoolValue) + { + (Chassis as DmMDMnxn).EnableAudioBreakaway.BoolValue = true; + (Chassis as DmMDMnxn).EnableUSBBreakaway.BoolValue = true; + + + EnableAudioBreakawayFeedback.FireUpdate(); + EnableUsbBreakawayFeedback.FireUpdate(); + + if (InputNames != null) + foreach (var kvp in InputNames) + Chassis.Inputs[kvp.Key].Name.StringValue = kvp.Value; + if (OutputNames != null) + foreach (var kvp in OutputNames) + Chassis.Outputs[kvp.Key].Name.StringValue = kvp.Value; + } + } + + #region IRouting Members + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType) + { Debug.Console(2, this, "Making an awesome DM route from {0} to {1} {2}", inputSelector, outputSelector, sigType); var input = inputSelector as DMInput;//Input Selector could be null... @@ -1185,34 +1185,34 @@ namespace PepperDash.Essentials.DM "Unable to execute switch for inputSelector {0} to outputSelector {1}", inputSelector, outputSelector); return; - } - - // Check to see if there's an off timer waiting on this and if so, cancel - var key = new PortNumberType(output, sigType); - if (input == null) - { - StartOffTimer(key); - } - else - { - if (RouteOffTimers.ContainsKey(key)) - { - Debug.Console(2, this, "{0} cancelling route off due to new source", output); - RouteOffTimers[key].Stop(); - RouteOffTimers.Remove(key); - } - } - - //var inCard = input == 0 ? null : Chassis.Inputs[input]; - //var outCard = input == 0 ? null : Chassis.Outputs[output]; - - // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES - if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) - { + } + + // Check to see if there's an off timer waiting on this and if so, cancel + var key = new PortNumberType(output, sigType); + if (input == null) + { + StartOffTimer(key); + } + else + { + if (RouteOffTimers.ContainsKey(key)) + { + Debug.Console(2, this, "{0} cancelling route off due to new source", output); + RouteOffTimers[key].Stop(); + RouteOffTimers.Remove(key); + } + } + + //var inCard = input == 0 ? null : Chassis.Inputs[input]; + //var outCard = input == 0 ? null : Chassis.Outputs[output]; + + // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES + if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) + { Chassis.VideoEnter.BoolValue = true; output.VideoOut = input; //Chassis.Outputs[output].VideoOut = inCard; - } - + } + if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) { var dmMdMnxn = Chassis as DmMDMnxn; @@ -1220,7 +1220,7 @@ namespace PepperDash.Essentials.DM { dmMdMnxn.AudioEnter.BoolValue = true; } - output.VideoOut = input; + output.AudioOut = input; //Chassis.Outputs[output].AudioOut = inCard; } @@ -1228,13 +1228,13 @@ namespace PepperDash.Essentials.DM { Chassis.USBEnter.BoolValue = true; output.USBRoutedTo = input; - } - - } - #endregion - - #region IRoutingNumeric Members - + } + + } + #endregion + + #region IRoutingNumeric Members + public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType) { var chassisSize = (uint)Chassis.NumberOfInputs; //need this to determine USB routing values 8x8 -> 1-8 is inputs 1-8, 17-24 is outputs 1-8 @@ -1303,37 +1303,37 @@ namespace PepperDash.Essentials.DM } var inputCard = inputSelector == 0 ? null : Chassis.Inputs[inputSelector]; - var outputCard = Chassis.Outputs[outputSelector]; - - ExecuteSwitch(inputCard, outputCard, sigType); - } - - #endregion - - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = GetJoinMap(joinStart, joinMapKey, bridge); - - Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - - LinkChassisToApi(trilist, joinMap); - - // Link up inputs & outputs - for (uint i = 1; i <= Chassis.NumberOfOutputs; i++) - { - var ioSlot = i; - var ioSlotJoin = ioSlot - 1; - - LinkRoutingJoinsToApi(trilist, joinMap, ioSlotJoin, ioSlot); - - if (TxDictionary.ContainsKey(ioSlot)) - { - LinkTxToApi(trilist, ioSlot, joinMap, ioSlotJoin); - } - else - { + var outputCard = Chassis.Outputs[outputSelector]; + + ExecuteSwitch(inputCard, outputCard, sigType); + } + + #endregion + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = GetJoinMap(joinStart, joinMapKey, bridge); + + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + LinkChassisToApi(trilist, joinMap); + + // Link up inputs & outputs + for (uint i = 1; i <= Chassis.NumberOfOutputs; i++) + { + var ioSlot = i; + var ioSlotJoin = ioSlot - 1; + + LinkRoutingJoinsToApi(trilist, joinMap, ioSlotJoin, ioSlot); + + if (TxDictionary.ContainsKey(ioSlot)) + { + LinkTxToApi(trilist, ioSlot, joinMap, ioSlotJoin); + } + else + { LinkHdmiInputToApi(trilist, ioSlot, joinMap, ioSlotJoin); - LinkStreamInputToApi(trilist, ioSlot, joinMap, ioSlotJoin); + LinkStreamInputToApi(trilist, ioSlot, joinMap, ioSlotJoin); } if (RxDictionary.ContainsKey(ioSlot)) @@ -1341,53 +1341,53 @@ namespace PepperDash.Essentials.DM LinkRxToApi(trilist, ioSlot, joinMap, ioSlotJoin); } else - LinkStreamOutputToApi(trilist, ioSlot, joinMap, ioSlotJoin); - } - } - - private void LinkHdmiInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) - { - VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); - - var inputPort = InputPorts[string.Format("inputCard{0}--hdmiIn", ioSlot)]; - if (inputPort == null) - { - return; - } - - Debug.Console(1, "Port value for input card {0} is set", ioSlot); - var port = inputPort.Port; - - if (port == null) - { - return; - } - if (!(port is HdmiInputWithCEC)) - { - Debug.Console(0, this, "HDMI Input port on card {0} does not support HDCP settings.", ioSlot); - return; - } - - Debug.Console(1, "Port is HdmiInputWithCec"); - - var hdmiInPortWCec = port as HdmiInputWithCEC; - - - SetHdcpStateAction(PropertiesConfig.InputSlotSupportsHdcp2[ioSlot], hdmiInPortWCec, joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); - - - InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( - trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); - - if (InputCardHdcpCapabilityTypes.ContainsKey(ioSlot)) - { - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = - (ushort)InputCardHdcpCapabilityTypes[ioSlot]; - } - else - { - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; - } + LinkStreamOutputToApi(trilist, ioSlot, joinMap, ioSlotJoin); + } + } + + private void LinkHdmiInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) + { + VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); + + var inputPort = InputPorts[string.Format("inputCard{0}--hdmiIn", ioSlot)]; + if (inputPort == null) + { + return; + } + + Debug.Console(1, "Port value for input card {0} is set", ioSlot); + var port = inputPort.Port; + + if (port == null) + { + return; + } + if (!(port is HdmiInputWithCEC)) + { + Debug.Console(0, this, "HDMI Input port on card {0} does not support HDCP settings.", ioSlot); + return; + } + + Debug.Console(1, "Port is HdmiInputWithCec"); + + var hdmiInPortWCec = port as HdmiInputWithCEC; + + + SetHdcpStateAction(PropertiesConfig.InputSlotSupportsHdcp2[ioSlot], hdmiInPortWCec, joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); + + + InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( + trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); + + if (InputCardHdcpCapabilityTypes.ContainsKey(ioSlot)) + { + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = + (ushort)InputCardHdcpCapabilityTypes[ioSlot]; + } + else + { + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; + } } private void LinkStreamInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) @@ -1468,448 +1468,448 @@ namespace PepperDash.Essentials.DM OutputStreamCardStateFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[join]); trilist.UShortInput[join].UShortValue = OutputStreamCardStateFeedbacks[ioSlot].UShortValue; - } - - private void LinkRxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) - { - Debug.Console(2, "Creating Rx Feedbacks {0}", ioSlot); - var rxKey = RxDictionary[ioSlot]; - var rxDevice = DeviceManager.GetDeviceForKey(rxKey) as DmRmcControllerBase; - var hdBaseTDevice = DeviceManager.GetDeviceForKey(rxKey) as DmHdBaseTControllerBase; - if (Chassis is DmMd8x8Cpu3 || Chassis is DmMd8x8Cpu3rps - || Chassis is DmMd16x16Cpu3 || Chassis is DmMd16x16Cpu3rps - || Chassis is DmMd32x32Cpu3 || Chassis is DmMd32x32Cpu3rps || hdBaseTDevice != null) - { - OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); - } - else if (rxDevice != null) - { - rxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); - } - } - - private void LinkTxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) - { - Debug.Console(1, "Setting up actions and feedbacks on input card {0}", ioSlot); - VideoInputSyncFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); - - Debug.Console(2, "Creating Tx Feedbacks {0}", ioSlot); - var txKey = TxDictionary[ioSlot]; - var txDevice = DeviceManager.GetDeviceForKey(txKey) as BasicDmTxControllerBase; - - if (txDevice == null) - { - return; - } - - LinkTxOnlineFeedbackToApi(trilist, ioSlot, joinMap, ioSlotJoin, txDevice); - - LinkBasicTxToApi(trilist, joinMap, ioSlot, ioSlotJoin, txDevice); - - LinkAdvancedTxToApi(trilist, joinMap, ioSlot, ioSlotJoin, txDevice); - } - - private void LinkBasicTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, uint ioSlot, - uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) - { - var advTx = basicTransmitter as DmTxControllerBase; - - if (advTx != null) - { - return; - } - var inputPort = InputPorts[string.Format("inputCard{0}--dmIn", ioSlot)]; - - if (inputPort == null) - { - return; - } - var port = inputPort.Port; - - if (!(port is DMInputPortWithCec)) - { - Debug.Console(0, this, "DM Input port on card {0} does not support HDCP settings.", ioSlot); - return; - } - Debug.Console(1, "Port is DMInputPortWithCec"); - - var dmInPortWCec = port as DMInputPortWithCec; - - bool supportsHdcp2; - - //added in case the InputSlotSupportsHdcp2 section isn't included in the config, or this slot is left out. - //if the key isn't in the dictionary, supportsHdcp2 will be false - - if(!PropertiesConfig.InputSlotSupportsHdcp2.TryGetValue(ioSlot, out supportsHdcp2)) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, - "Input Slot Supports HDCP2 setting not found for slot {0}. Setting to false. Program may not function as intended.", - ioSlot); - } - - SetHdcpStateAction(supportsHdcp2, dmInPortWCec, - joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); - - InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( - trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); - - if (InputCardHdcpCapabilityTypes.ContainsKey(ioSlot)) - { - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = - (ushort) InputCardHdcpCapabilityTypes[ioSlot]; - } - else - { - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; - } - } - - private void LinkAdvancedTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, - uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) - { - var transmitter = basicTransmitter as DmTxControllerBase; - if (transmitter == null) return; - - trilist.BooleanInput[joinMap.TxAdvancedIsPresent.JoinNumber + ioSlotJoin].BoolValue = true; - - transmitter.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig( - trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); - - var txRoutingInputs = transmitter as IRoutingInputs; - - if (txRoutingInputs == null) return; - - var inputPorts = txRoutingInputs.InputPorts.Where((p) => p.Port is EndpointHdmiInput || p.Port is EndpointDisplayPortInput).ToList(); - - if (inputPorts.Count == 0) - { - Debug.Console(1, this, "No HDCP-capable input ports found on transmitter for slot {0}", ioSlot); - return; - } - - bool supportsHdcp2; - - if (!PropertiesConfig.InputSlotSupportsHdcp2.TryGetValue(ioSlot, out supportsHdcp2)) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, - "Input Slot Supports HDCP2 setting not found for slot {0}. Setting to false. Program may not function as intended.", - ioSlot); - } - - SetHdcpStateAction(supportsHdcp2, inputPorts, joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); - - if (transmitter.HdcpStateFeedback != null) - { - transmitter.HdcpStateFeedback.LinkInputSig( - trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); - } - else - { - Debug.Console(2, this, "Transmitter Hdcp Feedback null. Linking to card's feedback"); - InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( - trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); - } - - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = - (ushort) transmitter.HdcpSupportCapability; - } - - private void LinkTxOnlineFeedbackToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, - uint ioSlotJoin, BasicDmTxControllerBase txDevice) - { - var advancedTxDevice = txDevice as DmTxControllerBase; - - if ((Chassis is DmMd8x8Cpu3 || Chassis is DmMd8x8Cpu3rps - || Chassis is DmMd16x16Cpu3 || Chassis is DmMd16x16Cpu3rps - || Chassis is DmMd32x32Cpu3 || Chassis is DmMd32x32Cpu3rps) || - advancedTxDevice == null) - { - Debug.Console(2, "Linking Tx Online Feedback from Input Card {0}", ioSlot); - InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); - return; - } - - Debug.Console(2, "Linking Tx Online Feedback from Advanced Transmitter at input {0}", ioSlot); - - advancedTxDevice.IsOnline.LinkInputSig( - trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); - } - - private void LinkRoutingJoinsToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, uint ioSlotJoin, - uint ioSlot) - { - // Routing Control - trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, - o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.Video)); + } + + private void LinkRxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) + { + Debug.Console(2, "Creating Rx Feedbacks {0}", ioSlot); + var rxKey = RxDictionary[ioSlot]; + var rxDevice = DeviceManager.GetDeviceForKey(rxKey) as DmRmcControllerBase; + var hdBaseTDevice = DeviceManager.GetDeviceForKey(rxKey) as DmHdBaseTControllerBase; + if (Chassis is DmMd8x8Cpu3 || Chassis is DmMd8x8Cpu3rps + || Chassis is DmMd16x16Cpu3 || Chassis is DmMd16x16Cpu3rps + || Chassis is DmMd32x32Cpu3 || Chassis is DmMd32x32Cpu3rps || hdBaseTDevice != null) + { + OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); + } + else if (rxDevice != null) + { + rxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); + } + } + + private void LinkTxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) + { + Debug.Console(1, "Setting up actions and feedbacks on input card {0}", ioSlot); + VideoInputSyncFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); + + Debug.Console(2, "Creating Tx Feedbacks {0}", ioSlot); + var txKey = TxDictionary[ioSlot]; + var txDevice = DeviceManager.GetDeviceForKey(txKey) as BasicDmTxControllerBase; + + if (txDevice == null) + { + return; + } + + LinkTxOnlineFeedbackToApi(trilist, ioSlot, joinMap, ioSlotJoin, txDevice); + + LinkBasicTxToApi(trilist, joinMap, ioSlot, ioSlotJoin, txDevice); + + LinkAdvancedTxToApi(trilist, joinMap, ioSlot, ioSlotJoin, txDevice); + } + + private void LinkBasicTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, uint ioSlot, + uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) + { + var advTx = basicTransmitter as DmTxControllerBase; + + if (advTx != null) + { + return; + } + var inputPort = InputPorts[string.Format("inputCard{0}--dmIn", ioSlot)]; + + if (inputPort == null) + { + return; + } + var port = inputPort.Port; + + if (!(port is DMInputPortWithCec)) + { + Debug.Console(0, this, "DM Input port on card {0} does not support HDCP settings.", ioSlot); + return; + } + Debug.Console(1, "Port is DMInputPortWithCec"); + + var dmInPortWCec = port as DMInputPortWithCec; + + bool supportsHdcp2; + + //added in case the InputSlotSupportsHdcp2 section isn't included in the config, or this slot is left out. + //if the key isn't in the dictionary, supportsHdcp2 will be false + + if(!PropertiesConfig.InputSlotSupportsHdcp2.TryGetValue(ioSlot, out supportsHdcp2)) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, + "Input Slot Supports HDCP2 setting not found for slot {0}. Setting to false. Program may not function as intended.", + ioSlot); + } + + SetHdcpStateAction(supportsHdcp2, dmInPortWCec, + joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); + + InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( + trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); + + if (InputCardHdcpCapabilityTypes.ContainsKey(ioSlot)) + { + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = + (ushort) InputCardHdcpCapabilityTypes[ioSlot]; + } + else + { + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; + } + } + + private void LinkAdvancedTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, + uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) + { + var transmitter = basicTransmitter as DmTxControllerBase; + if (transmitter == null) return; + + trilist.BooleanInput[joinMap.TxAdvancedIsPresent.JoinNumber + ioSlotJoin].BoolValue = true; + + transmitter.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig( + trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); + + var txRoutingInputs = transmitter as IRoutingInputs; + + if (txRoutingInputs == null) return; + + var inputPorts = txRoutingInputs.InputPorts.Where((p) => p.Port is EndpointHdmiInput || p.Port is EndpointDisplayPortInput).ToList(); + + if (inputPorts.Count == 0) + { + Debug.Console(1, this, "No HDCP-capable input ports found on transmitter for slot {0}", ioSlot); + return; + } + + bool supportsHdcp2; + + if (!PropertiesConfig.InputSlotSupportsHdcp2.TryGetValue(ioSlot, out supportsHdcp2)) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, + "Input Slot Supports HDCP2 setting not found for slot {0}. Setting to false. Program may not function as intended.", + ioSlot); + } + + SetHdcpStateAction(supportsHdcp2, inputPorts, joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); + + if (transmitter.HdcpStateFeedback != null) + { + transmitter.HdcpStateFeedback.LinkInputSig( + trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); + } + else + { + Debug.Console(2, this, "Transmitter Hdcp Feedback null. Linking to card's feedback"); + InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( + trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); + } + + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = + (ushort) transmitter.HdcpSupportCapability; + } + + private void LinkTxOnlineFeedbackToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, + uint ioSlotJoin, BasicDmTxControllerBase txDevice) + { + var advancedTxDevice = txDevice as DmTxControllerBase; + + if ((Chassis is DmMd8x8Cpu3 || Chassis is DmMd8x8Cpu3rps + || Chassis is DmMd16x16Cpu3 || Chassis is DmMd16x16Cpu3rps + || Chassis is DmMd32x32Cpu3 || Chassis is DmMd32x32Cpu3rps) || + advancedTxDevice == null) + { + Debug.Console(2, "Linking Tx Online Feedback from Input Card {0}", ioSlot); + InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); + return; + } + + Debug.Console(2, "Linking Tx Online Feedback from Advanced Transmitter at input {0}", ioSlot); + + advancedTxDevice.IsOnline.LinkInputSig( + trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); + } + + private void LinkRoutingJoinsToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, uint ioSlotJoin, + uint ioSlot) + { + // Routing Control + trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, + o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.Video)); trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin, - o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.Audio)); + o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.Audio)); trilist.SetUShortSigAction(joinMap.OutputUsb.JoinNumber + ioSlotJoin, - o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.UsbOutput)); + o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.UsbOutput)); trilist.SetUShortSigAction(joinMap.InputUsb.JoinNumber + ioSlotJoin, - o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.UsbInput)); - - //Routing Feedbacks - VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]); - AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]); - UsbOutputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputUsb.JoinNumber + ioSlotJoin]); - UsbInputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.InputUsb.JoinNumber + ioSlotJoin]); - - OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); - OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig( - trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]); - OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig( - trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]); - - OutputDisabledByHdcpFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.OutputDisabledByHdcp.JoinNumber + ioSlotJoin]); - } - - private void LinkChassisToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap) - { - var chassis = Chassis as DmMDMnxn; - - IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - - trilist.SetUShortSigAction(joinMap.SystemId.JoinNumber, o => - { - if (chassis != null) - { - chassis.SystemId.UShortValue = o; - } - }); - - trilist.SetSigTrueAction(joinMap.SystemId.JoinNumber, () => - { - if (chassis != null) - { - chassis.ApplySystemId(); - } - }); - - SystemIdFeebdack.LinkInputSig(trilist.UShortInput[joinMap.SystemId.JoinNumber]); - SystemIdBusyFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SystemId.JoinNumber]); - - EnableAudioBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAudioBreakaway.JoinNumber]); - EnableUsbBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsbBreakaway.JoinNumber]); - - trilist.OnlineStatusChange += (o, a) => - { - if (!a.DeviceOnLine) - { - return; - } - - EnableAudioBreakawayFeedback.FireUpdate(); - EnableUsbBreakawayFeedback.FireUpdate(); - SystemIdBusyFeedback.FireUpdate(); - SystemIdFeebdack.FireUpdate(); - }; - } - - private DmChassisControllerJoinMap GetJoinMap(uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new DmChassisControllerJoinMap(joinStart); - - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - - if (!string.IsNullOrEmpty(joinMapSerialized)) - { - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - } - - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.Console(0, this, - "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } - return joinMap; - } - - private void SetHdcpStateAction(bool supportsHdcp2, HdmiInputWithCEC port, uint join, BasicTriList trilist) - { - if (!supportsHdcp2) - { - trilist.SetUShortSigAction(join, - s => - { - if (s == 0) - { - Debug.Console(2, this, "Join {0} value {1} Setting HdcpSupport to off", join, s); - port.HdcpSupportOff(); - } - else if (s > 0) - { - Debug.Console(2, this, "Join {0} value {1} Setting HdcpSupport to on", join, s); - port.HdcpSupportOn(); - } - }); - } - else - { - trilist.SetUShortSigAction(join, - u => - { - Debug.Console(2, this, "Join {0} value {1} Setting HdcpReceiveCapability to: {2}", join, u, (eHdcpCapabilityType)u); - port.HdcpReceiveCapability = (eHdcpCapabilityType)u; - }); - } - } - - private void SetHdcpStateAction(bool supportsHdcp2, EndpointHdmiInput port, uint join, BasicTriList trilist) - { - if (!supportsHdcp2) - { - trilist.SetUShortSigAction(join, - s => - { - if (s == 0) - { - Debug.Console(2, this, "Join {0} value {1} Setting HdcpSupport to off", join, s); - port.HdcpSupportOff(); - } - else if (s > 0) - { - Debug.Console(2, this, "Join {0} value {1} Setting HdcpSupport to on", join, s); - port.HdcpSupportOn(); - } - }); - } - else - { - trilist.SetUShortSigAction(join, - u => - { - Debug.Console(2, this, "Join {0} value {1} Setting HdcpReceiveCapability to: {2}", join, u, (eHdcpCapabilityType)u); - port.HdcpCapability = (eHdcpCapabilityType)u; - }); - } - } - - private void SetHdcpStateAction(bool supportsHdcp2, List ports, uint join, - BasicTriList triList) - { - if (!supportsHdcp2) - { - triList.SetUShortSigAction(join, a => - { - foreach (var tempPort in ports.Select(port => port.Port).OfType()) - { - if (a == 0) - { - tempPort.HdcpSupportOff(); - } - else if (a > 0) - { - tempPort.HdcpSupportOn(); - } - } - }); - } - else - { - triList.SetUShortSigAction(join, a => - { - foreach (var tempPort in ports.Select(port => port.Port).OfType()) - { - tempPort.HdcpCapability = (eHdcpCapabilityType) a; - } - }); - } - } - - private void SetHdcpStateAction(bool supportsHdcp2, DMInputPortWithCec port, uint join, BasicTriList trilist) - { - if (!supportsHdcp2) - { - trilist.SetUShortSigAction(join, - s => - { - if (s == 0) - { - port.HdcpSupportOff(); - } - else if (s > 0) - { - port.HdcpSupportOn(); - } - }); - } - else - { - trilist.SetUShortSigAction(join, - u => - { - port.HdcpReceiveCapability = (eHdcpCapabilityType)u; - }); - } - } - } - - public struct PortNumberType - { - public uint Number { get; private set; } - public object Selector { get; private set; } - public eRoutingSignalType Type { get; private set; } - - public PortNumberType(object selector, eRoutingSignalType type) - : this() - { - Selector = selector; + o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.UsbInput)); + + //Routing Feedbacks + VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]); + AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]); + UsbOutputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputUsb.JoinNumber + ioSlotJoin]); + UsbInputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.InputUsb.JoinNumber + ioSlotJoin]); + + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); + OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig( + trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]); + OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig( + trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]); + + OutputDisabledByHdcpFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.OutputDisabledByHdcp.JoinNumber + ioSlotJoin]); + } + + private void LinkChassisToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap) + { + var chassis = Chassis as DmMDMnxn; + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + + trilist.SetUShortSigAction(joinMap.SystemId.JoinNumber, o => + { + if (chassis != null) + { + chassis.SystemId.UShortValue = o; + } + }); + + trilist.SetSigTrueAction(joinMap.SystemId.JoinNumber, () => + { + if (chassis != null) + { + chassis.ApplySystemId(); + } + }); + + SystemIdFeebdack.LinkInputSig(trilist.UShortInput[joinMap.SystemId.JoinNumber]); + SystemIdBusyFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SystemId.JoinNumber]); + + EnableAudioBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAudioBreakaway.JoinNumber]); + EnableUsbBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsbBreakaway.JoinNumber]); + + trilist.OnlineStatusChange += (o, a) => + { + if (!a.DeviceOnLine) + { + return; + } + + EnableAudioBreakawayFeedback.FireUpdate(); + EnableUsbBreakawayFeedback.FireUpdate(); + SystemIdBusyFeedback.FireUpdate(); + SystemIdFeebdack.FireUpdate(); + }; + } + + private DmChassisControllerJoinMap GetJoinMap(uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new DmChassisControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + { + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + } + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, + "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + return joinMap; + } + + private void SetHdcpStateAction(bool supportsHdcp2, HdmiInputWithCEC port, uint join, BasicTriList trilist) + { + if (!supportsHdcp2) + { + trilist.SetUShortSigAction(join, + s => + { + if (s == 0) + { + Debug.Console(2, this, "Join {0} value {1} Setting HdcpSupport to off", join, s); + port.HdcpSupportOff(); + } + else if (s > 0) + { + Debug.Console(2, this, "Join {0} value {1} Setting HdcpSupport to on", join, s); + port.HdcpSupportOn(); + } + }); + } + else + { + trilist.SetUShortSigAction(join, + u => + { + Debug.Console(2, this, "Join {0} value {1} Setting HdcpReceiveCapability to: {2}", join, u, (eHdcpCapabilityType)u); + port.HdcpReceiveCapability = (eHdcpCapabilityType)u; + }); + } + } + + private void SetHdcpStateAction(bool supportsHdcp2, EndpointHdmiInput port, uint join, BasicTriList trilist) + { + if (!supportsHdcp2) + { + trilist.SetUShortSigAction(join, + s => + { + if (s == 0) + { + Debug.Console(2, this, "Join {0} value {1} Setting HdcpSupport to off", join, s); + port.HdcpSupportOff(); + } + else if (s > 0) + { + Debug.Console(2, this, "Join {0} value {1} Setting HdcpSupport to on", join, s); + port.HdcpSupportOn(); + } + }); + } + else + { + trilist.SetUShortSigAction(join, + u => + { + Debug.Console(2, this, "Join {0} value {1} Setting HdcpReceiveCapability to: {2}", join, u, (eHdcpCapabilityType)u); + port.HdcpCapability = (eHdcpCapabilityType)u; + }); + } + } + + private void SetHdcpStateAction(bool supportsHdcp2, List ports, uint join, + BasicTriList triList) + { + if (!supportsHdcp2) + { + triList.SetUShortSigAction(join, a => + { + foreach (var tempPort in ports.Select(port => port.Port).OfType()) + { + if (a == 0) + { + tempPort.HdcpSupportOff(); + } + else if (a > 0) + { + tempPort.HdcpSupportOn(); + } + } + }); + } + else + { + triList.SetUShortSigAction(join, a => + { + foreach (var tempPort in ports.Select(port => port.Port).OfType()) + { + tempPort.HdcpCapability = (eHdcpCapabilityType) a; + } + }); + } + } + + private void SetHdcpStateAction(bool supportsHdcp2, DMInputPortWithCec port, uint join, BasicTriList trilist) + { + if (!supportsHdcp2) + { + trilist.SetUShortSigAction(join, + s => + { + if (s == 0) + { + port.HdcpSupportOff(); + } + else if (s > 0) + { + port.HdcpSupportOn(); + } + }); + } + else + { + trilist.SetUShortSigAction(join, + u => + { + port.HdcpReceiveCapability = (eHdcpCapabilityType)u; + }); + } + } + } + + public struct PortNumberType + { + public uint Number { get; private set; } + public object Selector { get; private set; } + public eRoutingSignalType Type { get; private set; } + + public PortNumberType(object selector, eRoutingSignalType type) + : this() + { + Selector = selector; Type = type; if (Selector is DMOutput) { Number = (selector as DMOutput).Number; - } + } else if (Selector is uint) { Number = (uint) selector; - } - } - } - - public class DmChassisControllerFactory : EssentialsDeviceFactory - { - public DmChassisControllerFactory() - { - TypeNames = new List() { "dmmd8x8", "dmmd8x8rps", "dmmd8x8cpu3", "dmmd8x8cpu3rps", - "dmmd16x16", "dmmd16x16rps", "dmmd16x16cpu3", "dmmd16x16cpu3rps", - "dmmd32x32", "dmmd32x32rps", "dmmd32x32cpu3", "dmmd32x32cpu3rps", - "dmmd64x64", "dmmd128x128" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - var type = dc.Type.ToLower(); - - Debug.Console(1, "Factory Attempting to create new DmChassisController Device"); - - if (type.StartsWith("dmmd8x") || type.StartsWith("dmmd16x") || type.StartsWith("dmmd32x")) - { - - var props = JsonConvert.DeserializeObject - (dc.Properties.ToString()); - return PepperDash.Essentials.DM.DmChassisController. - GetDmChassisController(dc.Key, dc.Name, type, props); - } - else if (type.StartsWith("dmmd128x") || type.StartsWith("dmmd64x")) - { - var props = JsonConvert.DeserializeObject - (dc.Properties.ToString()); - return PepperDash.Essentials.DM.DmBladeChassisController. - GetDmChassisController(dc.Key, dc.Name, type, props); - } - - return null; - } - } - + } + } + } + + public class DmChassisControllerFactory : EssentialsDeviceFactory + { + public DmChassisControllerFactory() + { + TypeNames = new List() { "dmmd8x8", "dmmd8x8rps", "dmmd8x8cpu3", "dmmd8x8cpu3rps", + "dmmd16x16", "dmmd16x16rps", "dmmd16x16cpu3", "dmmd16x16cpu3rps", + "dmmd32x32", "dmmd32x32rps", "dmmd32x32cpu3", "dmmd32x32cpu3rps", + "dmmd64x64", "dmmd128x128" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + var type = dc.Type.ToLower(); + + Debug.Console(1, "Factory Attempting to create new DmChassisController Device"); + + if (type.StartsWith("dmmd8x") || type.StartsWith("dmmd16x") || type.StartsWith("dmmd32x")) + { + + var props = JsonConvert.DeserializeObject + (dc.Properties.ToString()); + return PepperDash.Essentials.DM.DmChassisController. + GetDmChassisController(dc.Key, dc.Name, type, props); + } + else if (type.StartsWith("dmmd128x") || type.StartsWith("dmmd64x")) + { + var props = JsonConvert.DeserializeObject + (dc.Properties.ToString()); + return PepperDash.Essentials.DM.DmBladeChassisController. + GetDmChassisController(dc.Key, dc.Name, type, props); + } + + return null; + } + } + } \ No newline at end of file From d6445861f59efc98aeecf13f6ea8e5b77e4ba5c2 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 5 May 2021 21:55:28 -0600 Subject: [PATCH 09/28] Adds IHasZoomRoomLayouts interface. Update zStatus.Layout class to extend NotifiableObject --- .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 22 +++ .../VideoCodec/ZoomRoom/ResponseObjects.cs | 172 +++++++++++++++++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 39 ++++ 3 files changed, 226 insertions(+), 7 deletions(-) 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 131d610f..139935c0 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 @@ -19,4 +19,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec void LocalLayoutToggleSingleProminent(); void MinMaxLayoutToggle(); } + + /// + /// Defines the requirements for Zoom Room layout control + /// + public interface IHasZoomRoomLayouts : IHasCodecLayouts + { + BoolFeedback LayoutViewIsOnFirstPage { get; } + BoolFeedback LayoutViewIsOnLastPage { get; } + BoolFeedback CanSwitchWallView { get; } + BoolFeedback CanSwitchSpeakerView { get; } + BoolFeedback CanSwitchShareOnAllScreens { get; } + BoolFeedback CanSwapContentWithThumbnail { get; } + + List AvailableLayouts { get; } + + void GetLayouts(); // Mot sure this is necessary if we're already subscribed to zStatus Call Layout + void SetLayout(ZoomRoom.eZoomRoomLayoutStyle layoutStyle); + void SwapContentWithThumbnail(); + + void LayoutTurnNextPage(); + void LayoutTurnPreviousPage(); + } } \ No newline at end of file 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 36cce89f..a3ad932c 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,6 +23,46 @@ 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 @@ -551,18 +591,136 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } - public class Layout + public class Layout : NotifiableObject { + // backer variables + private bool _can_Switch_Speaker_View; + private bool _can_Switch_Wall_View; + private bool _can_Switch_Share_On_All_Screens; + private bool _is_In_First_Page; + private bool _is_In_Last_Page; + private string _video_type; + + public bool can_Adjust_Floating_Video { get; set; } public bool can_Switch_Floating_Share_Content { get; set; } - public bool can_Switch_Share_On_All_Screens { get; set; } - public bool can_Switch_Speaker_View { get; set; } - public bool can_Switch_Wall_View { get; set; } - public bool is_In_First_Page { get; set; } - public bool is_In_Last_Page { 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. + /// + [JsonProperty("can_Switch_Share_On_All_Screens")] + public bool can_Switch_Share_On_All_Screens + { + get + { + return _can_Switch_Share_On_All_Screens; + } + set + { + if (value != _can_Switch_Share_On_All_Screens) + { + _can_Switch_Share_On_All_Screens = value; + NotifyPropertyChanged("can_Switch_Share_On_All_Screens"); + } + } + } + + /// + /// [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. + /// + [JsonProperty("can_Switch_Speaker_View")] + public bool can_Switch_Speaker_View + { + get + { + return _can_Switch_Speaker_View; + } + set + { + if (value != _can_Switch_Speaker_View) + { + _can_Switch_Speaker_View = value; + NotifyPropertyChanged("can_Switch_Speaker_View"); + } + } + } + + /// + /// [on/off] On if it is possible to invoke zConfiguration Call Layout Style: Gallery, to switch to the Gallery mode, showing video participants in tiled windows: The Zoom Room shows up to a 5x5 array of tiled windows per page. + /// + [JsonProperty("can_Switch_Wall_View")] + public bool can_Switch_Wall_View + { + get + { + return _can_Switch_Wall_View; + } + set + { + if (value != _can_Switch_Wall_View) + { + _can_Switch_Wall_View = value; + NotifyPropertyChanged("can_Switch_Wall_View"); + } + } + } + + [JsonProperty("is_In_First_Page")] + public bool is_In_First_Page + { + get + { + return _is_In_First_Page; + } + set + { + if (value != _is_In_First_Page) + { + _is_In_First_Page = value; + NotifyPropertyChanged("is_In_First_Page"); + } + } + } + + [JsonProperty("is_In_Last_Page")] + public bool is_In_Last_Page + { + get + { + return _is_In_Last_Page; + } + set + { + if (value != _is_In_Last_Page) + { + _is_In_Last_Page = value; + NotifyPropertyChanged("is_In_Last_Page"); + } + } + } + public bool is_supported { get; set; } public int video_Count_In_Current_Page { get; set; } - public string video_type { get; set; } + + /// + /// [Gallery | Strip] Indicates which mode applies: Strip or Gallery. + /// + [JsonProperty("video_type")] + public string video_type + { + get + { + return _video_type; + } + set + { + if (value != _video_type) + { + _video_type = value; + NotifyPropertyChanged("video_type"); + } + } + } } public class CallRecordInfo 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 42a389a7..905957f2 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 @@ -542,6 +542,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom break; } }; + + Status.Layout.PropertyChanged += (o, a) => + { + 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) + break; + } + case "is_In_First_Page": + { + // TODO: #697 Fire appropriate feedback(s) + // + break; + } + case "is_In_Last_Page": + { + // TODO: #697 Fire appropriate feedback(s) + break; + } + case "video_type": + { + // TODO: #697 Fire appropriate feedback(s) + // LocalLayoutFeedback.FireUpdate(); + break; + } + } + }; } private void SetUpDirectory() From e4a39337434ed896f5dab3801187adb735e341e4 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 6 May 2021 16:54:41 -0600 Subject: [PATCH 10/28] 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 From 2d7ad8ba2a08b53f6d7b4811a1c99de78f767493 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 7 May 2021 18:07:25 -0600 Subject: [PATCH 11/28] #698 Updates to add participant hand raised and pin/unpin --- .../VideoCodec/Interfaces/IHasParticipants.cs | 47 +++- .../VideoCodec/VideoCodecBase.cs | 20 +- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 30 ++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 200 ++++++++++++++++-- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 20 ++ 5 files changed, 284 insertions(+), 33 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs index e0f1d1a3..f03c1984 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasParticipants.cs @@ -1,13 +1,20 @@ using System; using System.Collections.Generic; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { + /// + /// Describes a device that has call participants + /// public interface IHasParticipants { CodecParticipants Participants { get; } } + /// + /// Describes the ability to mute and unmute a participant's video in a meeting + /// public interface IHasParticipantVideoMute:IHasParticipants { void MuteVideoForParticipant(int userId); @@ -15,13 +22,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces void ToggleVideoForParticipant(int userId); } - public interface IHasParticipantAudioMute:IHasParticipantVideoMute + /// + /// Describes the ability to mute and unmute a participant's audio in a meeting + /// + public interface IHasParticipantAudioMute : IHasParticipantVideoMute { void MuteAudioForParticipant(int userId); void UnmuteAudioForParticipant(int userId); void ToggleAudioForParticipant(int userId); } + /// + /// Describes the ability to pin and unpin a participant in a meeting + /// + public interface IHasParticipantPinUnpin : IHasParticipants + { + IntFeedback NumberOfScreensFeedback { get; } + int ScreenIndexToPinUserTo { get; } + + void PinParticipant(int userId, int screenIndex); + void UnPinParticipant(int userId); + void ToggleParticipantPinState(int userId, int screenIndex); + } + public class CodecParticipants { private List _currentParticipants; @@ -31,11 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces set { _currentParticipants = value; - var handler = ParticipantsListHasChanged; - - if(handler == null) return; - - handler(this, new EventArgs()); + OnParticipantsChanged(); } } @@ -45,15 +64,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { _currentParticipants = new List(); } + + public void OnParticipantsChanged() + { + var handler = ParticipantsListHasChanged; + + if (handler == null) return; + + handler(this, new EventArgs()); + } } + /// + /// Represents a call participant + /// public class Participant { + public int UserId { get; set; } public bool IsHost { get; set; } public string Name { get; set; } public bool CanMuteVideo { get; set; } public bool CanUnmuteVideo { get; set; } public bool VideoMuteFb { get; set; } public bool AudioMuteFb { get; set; } + public bool HandIsRaisedFb { get; set; } + public bool IsPinnedFb { get; set; } + public int ScreenIndexIsPinnedToFb { 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 7b2f7f42..1cdb6bc7 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 @@ -547,16 +547,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetUshort(joinMap.ParticipantCount.JoinNumber, (ushort)codec.Participants.CurrentParticipants.Count); }; + + // TODO: #698 Figure out how to decode xsig data and trigger actions based on values from SIMPL + // trilist.SetStringSigAction(joinMap.CurrentParticipants.JoinNumber, // add method here to decode the xsig info and trigger actions } private string UpdateParticipantsXSig(List currentParticipants) { const int maxParticipants = 50; - const int maxDigitals = 5; + const int maxDigitals = 7; const int maxStrings = 1; + const int maxAnalogs = 1; const int offset = maxDigitals + maxStrings; var digitalIndex = maxStrings * maxParticipants; //15 var stringIndex = 0; + var analogIndex = 0; var meetingIndex = 0; var tokenArray = new XSigToken[maxParticipants * offset]; @@ -571,29 +576,42 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, participant.CanMuteVideo); tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, participant.CanUnmuteVideo); tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, participant.IsHost); + tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, participant.HandIsRaisedFb); + tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 6, participant.IsPinnedFb); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, participant.Name); + //analogs + tokenArray[analogIndex] = new XSigAnalogToken(analogIndex + 1, (ushort)participant.ScreenIndexIsPinnedToFb); + digitalIndex += maxDigitals; meetingIndex += offset; stringIndex += maxStrings; + analogIndex += maxAnalogs; } while (meetingIndex < maxParticipants * offset) { + //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, false); tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, false); tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, false); + tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, false); + tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, false); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + //analogs + tokenArray[analogIndex] = new XSigAnalogToken(analogIndex + 1, 0); + digitalIndex += maxDigitals; meetingIndex += offset; stringIndex += maxStrings; + analogIndex += maxAnalogs; } return GetXSigString(tokenArray); 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 6720d4fc..c8bfd5bf 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 @@ -480,12 +480,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public string wifiName { get; set; } } - public class NumberOfScreens + public class NumberOfScreens : NotifiableObject { + private int _numOfScreens; + [JsonProperty("NumberOfCECScreens")] public int NumOfCECScreens { get; set; } [JsonProperty("NumberOfScreens")] - public int NumOfScreens { get; set; } + public int NumOfScreens + { + get + { + return _numOfScreens; + } + set + { + if (value != _numOfScreens) + { + _numOfScreens = value; + NotifyPropertyChanged("NumberOfScreens"); + } + } + } } /// @@ -803,6 +819,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public class PinStatusOfScreenNotification { + + [JsonProperty("can_be_pinned")] public bool CanBePinned { get; set; } [JsonProperty("can_pin_share")] @@ -1301,8 +1319,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { [JsonProperty("is_raise_hand")] public bool IsRaiseHand { get; set; } - [JsonProperty("optimize_vis_validideo_sharing")] - public string IsValid { get; set; } + [JsonProperty("is_valid")] + public bool IsValid { get; set; } [JsonProperty("time_stamp")] public string TimeStamp { get; set; } } @@ -1377,12 +1395,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom p => new Participant { + UserId = p.UserId, Name = p.UserName, IsHost = p.IsHost, CanMuteVideo = p.IsVideoCanMuteByHost, CanUnmuteVideo = p.IsVideoCanUnmuteByHost, AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED", - VideoMuteFb = p.VideoStatusIsSending + VideoMuteFb = p.VideoStatusIsSending, + HandIsRaisedFb = p.HandStatus.IsValid && p.HandStatus.IsRaiseHand, }).ToList(); } } 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 da8f0d67..a0a8158c 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, IHasZoomRoomLayouts + IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasParticipantAudioMute { private const long MeetingRefreshTimer = 60000; private const uint DefaultMeetingDurationMin = 30; @@ -125,13 +125,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom LocalLayoutFeedback = new StringFeedback(LocalLayoutFeedbackFunc); LayoutViewIsOnFirstPageFeedback = new BoolFeedback(LayoutViewIsOnFirstPageFeedbackFunc); - LayoutViewIsOnLastPageFeedback = new BoolFeedback(LayoutViewIsOnLastPageFeedbackFunc); - CanSwapContentWithThumbnailFeedback = new BoolFeedback(CanSwapContentWithThumbnailFeedbackFunc); - ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc); + NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc); + } public CommunicationGather PortGather { get; private set; } @@ -574,30 +573,39 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom case "can_Switch_Wall_View": case "can_Switch_Share_On_All_Screens": { - // #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 Fires appropriate feedback LayoutViewIsOnFirstPageFeedback.FireUpdate(); break; } case "is_In_Last_Page": { - // 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 + // It appears as though the actual value we want to watch is Configuration.Call.Layout.Style // LocalLayoutFeedback.FireUpdate(); // break; // } } }; + + Status.NumberOfScreens.PropertyChanged += (o, a) => + { + switch (a.PropertyName) + { + case "NumberOfScreens": + { + NumberOfScreensFeedback.FireUpdate(); + break; + } + } + }; } private void SetUpDirectory() @@ -1278,6 +1286,38 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); break; } + case "pinstatusofscreennotification": + { + var status = responseObj.ToObject(); + + var participant = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(status.PinnedUserId)); + + if (participant != null) + { + participant.IsPinnedFb = true; + participant.ScreenIndexIsPinnedToFb = status.ScreenIndex; + } + else + { + participant = Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); + + if (participant == null) + { + Debug.Console(2, this, "no matching participant found by pinned_user_id: {0} or screen_index: {1}", status.PinnedUserId, status.ScreenIndex); + return; + } + else + { + participant.IsPinnedFb = false; + participant.ScreenIndexIsPinnedToFb = -1; + } + } + + // fire the event as we've modified the participants list + Participants.OnParticipantsChanged(); + + break; + } default: { break; @@ -1682,11 +1722,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom /// public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap) { - var codec = this as IHasZoomRoomLayouts; + var layoutsCodec = this as IHasZoomRoomLayouts; - if (codec != null) + if (layoutsCodec != null) { - codec.AvailableLayoutsChanged += (o, a) => + layoutsCodec.AvailableLayoutsChanged += (o, a) => { trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, a.AvailableLayouts == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery)); @@ -1698,14 +1738,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom == (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]); + layoutsCodec.CanSwapContentWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]); + trilist.SetSigFalseAction(joinMap.SwapContentWithThumbnail.JoinNumber, () => layoutsCodec.SwapContentWithThumbnail()); + layoutsCodec.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()); + layoutsCodec.LayoutViewIsOnFirstPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnFirstPage.JoinNumber]); + layoutsCodec.LayoutViewIsOnLastPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnLastPage.JoinNumber]); + trilist.SetSigFalseAction(joinMap.LayoutTurnToNextPage.JoinNumber, () => layoutsCodec.LayoutTurnNextPage()); + trilist.SetSigFalseAction(joinMap.LayoutTurnToPreviousPage.JoinNumber, () => layoutsCodec.LayoutTurnPreviousPage()); trilist.SetStringSigAction(joinMap.GetSetCurrentLayout.JoinNumber, (s) => @@ -1721,9 +1761,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } }); - codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); + layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); + } - + var pinCodec = this as IHasParticipantPinUnpin; + + if (pinCodec != null) + { + pinCodec.NumberOfScreensFeedback.LinkInputSig(trilist.UShortInput[joinMap.NumberOfScreens.JoinNumber]); + + // Set the value of the local property to be used when pinning a participant + trilist.SetUShortSigAction(joinMap.ScreenIndexToPinUserTo.JoinNumber, (u) => ScreenIndexToPinUserTo = u); } } @@ -1894,6 +1942,114 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom #endregion + #region IHasParticipantAudioMute Members + + public void MuteAudioForParticipant(int userId) + { + SendText(string.Format("zCommand Call MuteParticipant Mute: on Id: {0}", userId)); + } + + public void UnmuteAudioForParticipant(int userId) + { + SendText(string.Format("zCommand Call MuteParticipant Mute: off Id: {0}", userId)); + } + + public void ToggleAudioForParticipant(int userId) + { + var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); + + if (user == null) + { + Debug.Console(2, this, "Unable to find user with id: {0}", userId); + return; + } + + if (user.AudioMuteFb) + { + UnmuteAudioForParticipant(userId); + } + else + { + MuteAudioForParticipant(userId); + } + } + + #endregion + + #region IHasParticipantVideoMute Members + + public void MuteVideoForParticipant(int userId) + { + SendText(string.Format("zCommand Call MuteParticipantVideo Mute: on Id: {0}", userId)); + } + + public void UnmuteVideoForParticipant(int userId) + { + SendText(string.Format("zCommand Call MuteParticipantVideo Mute: off Id: {0}", userId)); + } + + public void ToggleVideoForParticipant(int userId) + { + var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); + + if (user == null) + { + Debug.Console(2, this, "Unable to find user with id: {0}", userId); + return; + } + + if (user.VideoMuteFb) + { + UnmuteVideoForParticipant(userId); + } + else + { + MuteVideoForParticipant(userId); + } + } + + #endregion + + #region IHasParticipantPinUnpin Members + + private Func NumberOfScreensFeedbackFunc { get { return () => Status.NumberOfScreens.NumOfScreens; } } + + public IntFeedback NumberOfScreensFeedback { get; private set; } + + public int ScreenIndexToPinUserTo { get; private set; } + + public void PinParticipant(int userId, int screenIndex) + { + SendText(string.Format("zCommand Call Pin Id: {0} Enable: on Screen: {1}", userId, screenIndex)); + } + + public void UnPinParticipant(int userId) + { + SendText(string.Format("zCommand Call Pin Id: {0} Enable: off", userId)); + } + + public void ToggleParticipantPinState(int userId, int screenIndex) + { + var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); + + if(user == null) + { + Debug.Console(2, this, "Unable to find user with id: {0}", userId); + return; + } + + if (user.IsPinnedFb) + { + UnPinParticipant(userId); + } + else + { + PinParticipant(userId, screenIndex); + } + } + + #endregion + #region Implementation of IHasCameraOff public BoolFeedback CameraIsOffFeedback { get; private set; } @@ -2052,7 +2208,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void ComputeAvailableLayouts() { zConfiguration.eLayoutStyle availableLayouts = zConfiguration.eLayoutStyle.None; - //TODO: #697 Compute the avaialble layouts and set the value of AvailableLayouts + // TODO: #697 Compute the avaialble layouts and set the value of AvailableLayouts + // Will need to test and confirm that this logic evaluates correctly if (Status.Layout.can_Switch_Wall_View) { availableLayouts |= zConfiguration.eLayoutStyle.Gallery; @@ -2140,6 +2297,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } #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 index 49b22ae4..f4d11f14 100644 --- 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 @@ -128,6 +128,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); + [JoinName("ScreenIndexToPinUserTo")] + public JoinDataComplete ScreenIndexToPinUserTo = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Specifies the screen index a participant should be pinned to", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("NumberOfScreens")] + public JoinDataComplete NumberOfScreens = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Reports the number of screens connected", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + public ZoomRoomJoinMap(uint joinStart) : base(joinStart, typeof(ZoomRoomJoinMap)) { From 604f4ca22d3fed419ef791b53950895c431c8d16 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 10 May 2021 12:58:07 -0600 Subject: [PATCH 12/28] #698 Adds join objects for participants audio/video mute and pin toggle --- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) 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 index f4d11f14..fd0e9a4a 100644 --- 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 @@ -148,6 +148,36 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Analog }); + [JoinName("ParticipantAudioMuteToggleStart")] + public JoinDataComplete ParticipantAudioMuteToggleStart = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Toggles the participant's audio mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ParticipantVideoMuteToggleStart")] + public JoinDataComplete ParticipantVideoMuteToggleStart = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Toggles the participant's video mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ParticipantPinToggleStart")] + public JoinDataComplete ParticipantPinToggleStart = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Toggles the participant's pin status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + public ZoomRoomJoinMap(uint joinStart) : base(joinStart, typeof(ZoomRoomJoinMap)) { From d937dc14fcbfa15326ae4dfe4e80ea2c1b8a5bca Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 10 May 2021 15:09:33 -0600 Subject: [PATCH 13/28] #698 Adds actions to toggle audio/video mute and pinning for participants --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 66 +++++++++++++++++++ .../VideoCodec/VideoCodecBase.cs | 51 +++++++++++++- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 3 +- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 29 -------- 4 files changed, 117 insertions(+), 32 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 284b8043..fde2b551 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -879,6 +879,39 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + // TODO: #698 Set Join number + [JoinName("ParticipantAudioMuteToggleStart")] + public JoinDataComplete ParticipantAudioMuteToggleStart = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 50 }, + new JoinMetadata + { + Description = "Toggles the participant's audio mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + // TODO: #698 Set Join number + [JoinName("ParticipantVideoMuteToggleStart")] + public JoinDataComplete ParticipantVideoMuteToggleStart = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 50 }, + new JoinMetadata + { + Description = "Toggles the participant's video mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + // TODO: #698 Set Join number + [JoinName("ParticipantPinToggleStart")] + public JoinDataComplete ParticipantPinToggleStart = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 50 }, + new JoinMetadata + { + Description = "Toggles the participant's pin status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof(VideoCodecControllerJoinMap)) { @@ -1773,6 +1806,39 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + // TODO: #698 Set Join number + [JoinName("ParticipantAudioMuteToggleStart")] + public JoinDataComplete ParticipantAudioMuteToggleStart = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 50 }, + new JoinMetadata + { + Description = "Toggles the participant's audio mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + // TODO: #698 Set Join number + [JoinName("ParticipantVideoMuteToggleStart")] + public JoinDataComplete ParticipantVideoMuteToggleStart = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 50 }, + new JoinMetadata + { + Description = "Toggles the participant's video mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + // TODO: #698 Set Join number + [JoinName("ParticipantPinToggleStart")] + public JoinDataComplete ParticipantPinToggleStart = + new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 50 }, + new JoinMetadata + { + Description = "Toggles the participant's pin status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof(VideoCodecControllerJoinMap)) { 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 1cdb6bc7..8ea7d86b 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 @@ -28,6 +28,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced { private const int XSigEncoding = 28591; + protected const int MaxParticipants = 50; private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs(); protected VideoCodecBase(DeviceConfig config) : base(config) @@ -541,6 +542,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec return; } + SetParticipantActions(trilist, joinMap, codec.Participants.CurrentParticipants); + participantsXSig = UpdateParticipantsXSig(codec.Participants.CurrentParticipants); trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig); @@ -550,11 +553,55 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec // TODO: #698 Figure out how to decode xsig data and trigger actions based on values from SIMPL // trilist.SetStringSigAction(joinMap.CurrentParticipants.JoinNumber, // add method here to decode the xsig info and trigger actions + } + /// + /// Sets the actions for each participant in the list + /// + private void SetParticipantActions(BasicTriList trilist, VideoCodecControllerJoinMap joinMap, List currentParticipants) + { + uint index = 0; // track the index of the participant in the + + foreach (var participant in currentParticipants) + { + var p = participant; + if (index > MaxParticipants) break; + + var audioMuteCodec = this as IHasParticipantAudioMute; + if (audioMuteCodec != null) + { + trilist.SetSigFalseAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index, + () => audioMuteCodec.ToggleAudioForParticipant(p.UserId)); + + trilist.SetSigFalseAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index, + () => audioMuteCodec.ToggleVideoForParticipant(p.UserId)); + } + + var pinCodec = this as IHasParticipantPinUnpin; + if (pinCodec != null) + { + trilist.SetSigFalseAction(joinMap.ParticipantPinToggleStart.JoinNumber + index, + () => pinCodec.ToggleParticipantPinState(p.UserId, pinCodec.ScreenIndexToPinUserTo)); + } + + index++; + } + + // Clear out any previously set actions + while (index < MaxParticipants) + { + trilist.ClearBoolSigAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index); + trilist.ClearBoolSigAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index); + trilist.ClearBoolSigAction(joinMap.ParticipantPinToggleStart.JoinNumber + index); + + index++; + } + } + private string UpdateParticipantsXSig(List currentParticipants) { - const int maxParticipants = 50; + const int maxParticipants = MaxParticipants; const int maxDigitals = 7; const int maxStrings = 1; const int maxAnalogs = 1; @@ -577,7 +624,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, participant.CanUnmuteVideo); tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, participant.IsHost); tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, participant.HandIsRaisedFb); - tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 6, participant.IsPinnedFb); + tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, participant.IsPinnedFb); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, participant.Name); 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 a0a8158c..2759e259 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 @@ -1761,7 +1761,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } }); - layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); + layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); + } var pinCodec = this as IHasParticipantPinUnpin; 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 index fd0e9a4a..02e04caa 100644 --- 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 @@ -148,35 +148,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Analog }); - [JoinName("ParticipantAudioMuteToggleStart")] - public JoinDataComplete ParticipantAudioMuteToggleStart = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Toggles the participant's audio mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ParticipantVideoMuteToggleStart")] - public JoinDataComplete ParticipantVideoMuteToggleStart = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Toggles the participant's video mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ParticipantPinToggleStart")] - public JoinDataComplete ParticipantPinToggleStart = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Toggles the participant's pin status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); public ZoomRoomJoinMap(uint joinStart) : base(joinStart, typeof(ZoomRoomJoinMap)) From a06333e1c36e32b32b44f57acf0dda989caa2292 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 10 May 2021 15:38:33 -0600 Subject: [PATCH 14/28] Adds temp join numbers for participant actions --- .../Bridges/JoinMaps/VideoCodecControllerJoinMap.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index fde2b551..28abed79 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -882,7 +882,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps // TODO: #698 Set Join number [JoinName("ParticipantAudioMuteToggleStart")] public JoinDataComplete ParticipantAudioMuteToggleStart = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 50 }, + new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 50 }, new JoinMetadata { Description = "Toggles the participant's audio mute status", @@ -893,7 +893,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps // TODO: #698 Set Join number [JoinName("ParticipantVideoMuteToggleStart")] public JoinDataComplete ParticipantVideoMuteToggleStart = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 50 }, + new JoinDataComplete(new JoinData { JoinNumber = 2101, JoinSpan = 50 }, new JoinMetadata { Description = "Toggles the participant's video mute status", @@ -904,7 +904,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps // TODO: #698 Set Join number [JoinName("ParticipantPinToggleStart")] public JoinDataComplete ParticipantPinToggleStart = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 50 }, + new JoinDataComplete(new JoinData { JoinNumber = 2201, JoinSpan = 50 }, new JoinMetadata { Description = "Toggles the participant's pin status", From 116abbf96276b5bb1f23cd30b4af34ae0dd28a38 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 11 May 2021 08:34:16 -0500 Subject: [PATCH 15/28] Updates ZoomRoomJoinMap.cs with join numbers. Updated VideoCodecControllerJoinMap.cs to organize the joins in a logical pattern. Update VideoCodecBase to add the maxAnalogs to the logic calculating xsig indexes and offsets. --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 3916 +++++++++-------- .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 4 +- .../VideoCodec/VideoCodecBase.cs | 306 +- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 24 +- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 412 +- 5 files changed, 2573 insertions(+), 2089 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 284b8043..1b6d9483 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -2,1785 +2,2147 @@ using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Core.Bridges.JoinMaps { - public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced - { - #region Status - - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = - new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Device is Online", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - #endregion - - [JoinName("CallDirection")] - public JoinDataComplete CallDirection = - new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Call Direction", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraLayout")] - public JoinDataComplete CameraLayout = - new JoinDataComplete(new JoinData { JoinNumber = 142, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Layout Toggle", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraLayoutStringFb")] - public JoinDataComplete CameraLayoutStringFb = - new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Layout Fb", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraModeAuto")] - public JoinDataComplete CameraModeAuto = - new JoinDataComplete(new JoinData { JoinNumber = 131, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Mode Auto", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeManual")] - public JoinDataComplete CameraModeManual = - new JoinDataComplete(new JoinData { JoinNumber = 132, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Mode Manual", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeOff")] - public JoinDataComplete CameraModeOff = - new JoinDataComplete(new JoinData { JoinNumber = 133, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Mode Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraNumberSelect")] - public JoinDataComplete CameraNumberSelect = - new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Number Select/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraPanLeft")] - public JoinDataComplete CameraPanLeft = - new JoinDataComplete(new JoinData { JoinNumber = 113, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Pan Left", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPanRight")] - public JoinDataComplete CameraPanRight = - new JoinDataComplete(new JoinData { JoinNumber = 114, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Pan Right", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPresetNames")] - public JoinDataComplete CameraPresetNames = - new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Preset Names - XSIG, max of 15", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraPresetSelect")] - public JoinDataComplete CameraPresetSelect = - new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Preset Select", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraPresetSave")] - public JoinDataComplete CameraPresetSave = - new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Save Selected Preset", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSelfView")] - public JoinDataComplete CameraSelfView = - new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Self View Toggle/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsAutoMode")] - public JoinDataComplete CameraSupportsAutoMode = - new JoinDataComplete(new JoinData { JoinNumber = 143, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Supports Auto Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsOffMode")] - public JoinDataComplete CameraSupportsOffMode = - new JoinDataComplete(new JoinData { JoinNumber = 144, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Supports Off Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltDown")] - public JoinDataComplete CameraTiltDown = - new JoinDataComplete(new JoinData { JoinNumber = 112, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Tilt Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltUp")] - public JoinDataComplete CameraTiltUp = - new JoinDataComplete(new JoinData { JoinNumber = 111, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Tilt Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomIn")] - public JoinDataComplete CameraZoomIn = - new JoinDataComplete(new JoinData { JoinNumber = 115, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Zoom In", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomOut")] - public JoinDataComplete CameraZoomOut = - new JoinDataComplete(new JoinData { JoinNumber = 116, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CurrentCallName")] - public JoinDataComplete CurrentCallData = - new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Call Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentDialString")] - public JoinDataComplete CurrentDialString = - new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Dial String", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentParticipants")] - public JoinDataComplete CurrentParticipants = - new JoinDataComplete(new JoinData { JoinNumber = 151, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Participants XSig", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentSource")] - public JoinDataComplete CurrentSource = - new JoinDataComplete(new JoinData { JoinNumber = 201, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Source", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DialMeeting1")] - public JoinDataComplete DialMeeting1 = - new JoinDataComplete(new JoinData { JoinNumber = 161, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Join first meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting2")] - public JoinDataComplete DialMeeting2 = - new JoinDataComplete(new JoinData { JoinNumber = 162, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Join second meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting3")] - public JoinDataComplete DialMeeting3 = - new JoinDataComplete(new JoinData { JoinNumber = 163, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Join third meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryDialSelectedLine")] - public JoinDataComplete DirectoryDialSelectedLine = - new JoinDataComplete(new JoinData { JoinNumber = 106, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial selected directory line", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryEntries")] - public JoinDataComplete DirectoryEntries = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Entries - XSig, 255 entries", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntryIsContact")] - public JoinDataComplete DirectoryEntryIsContact = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Selected Entry Is Contact FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryEntrySelectedName")] - public JoinDataComplete DirectoryEntrySelectedName = - new JoinDataComplete(new JoinData { JoinNumber = 356, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Selected Directory Entry Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntrySelectedNumber")] - public JoinDataComplete DirectoryEntrySelectedNumber = - new JoinDataComplete(new JoinData { JoinNumber = 357, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Selected Directory Entry Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryFolderBack")] - public JoinDataComplete DirectoryFolderBack = - new JoinDataComplete(new JoinData { JoinNumber = 105, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Go back one directory level", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryHasChanged")] - public JoinDataComplete DirectoryHasChanged = - new JoinDataComplete(new JoinData { JoinNumber = 103, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory has changed FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryIsRoot")] - public JoinDataComplete DirectoryIsRoot = - new JoinDataComplete(new JoinData { JoinNumber = 102, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory is on Root FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryLineSelected")] - public JoinDataComplete DirectoryLineSelected = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Line Selected FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryRoot")] - public JoinDataComplete DirectoryRoot = - new JoinDataComplete(new JoinData { JoinNumber = 104, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Go to Directory Root", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryRowCount")] - public JoinDataComplete DirectoryRowCount = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Row Count FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectorySearchBusy")] - public JoinDataComplete DirectorySearchBusy = - new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Search Busy FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectorySearchString")] - public JoinDataComplete DirectorySearchString = - new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Search String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectorySelectRow")] - public JoinDataComplete DirectorySelectRow = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Select Row", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectorySelectedFolderName")] - public JoinDataComplete DirectorySelectedFolderName = - new JoinDataComplete(new JoinData { JoinNumber = 358, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Selected Directory Folder Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("0")] - public JoinDataComplete Dtmf0 = - new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 0", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("1")] - public JoinDataComplete Dtmf1 = - new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 1", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("2")] - public JoinDataComplete Dtmf2 = - new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 2", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("3")] - public JoinDataComplete Dtmf3 = - new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 3", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("4")] - public JoinDataComplete Dtmf4 = - new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 4", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("5")] - public JoinDataComplete Dtmf5 = - new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 5", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("6")] - public JoinDataComplete Dtmf6 = - new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 6", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("7")] - public JoinDataComplete Dtmf7 = - new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 7", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("8")] - public JoinDataComplete Dtmf8 = - new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 8", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("9")] - public JoinDataComplete Dtmf9 = - new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 9", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("#")] - public JoinDataComplete DtmfPound = - new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF #", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("*")] - public JoinDataComplete DtmfStar = - new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF *", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("EndCall")] - public JoinDataComplete EndCall = - new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Hang Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("HookState")] - public JoinDataComplete HookState = - new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Hook State", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingAnswer")] - public JoinDataComplete IncomingAnswer = - new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Answer Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCall")] - public JoinDataComplete IncomingCall = - new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Incoming Call", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCallName")] - public JoinDataComplete IncomingCallName = - new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Incoming Call Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallNumber")] - public JoinDataComplete IncomingCallNumber = - new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Incoming Call Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingReject")] - public JoinDataComplete IncomingReject = - new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Reject Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - - [JoinName("ManualDial")] - public JoinDataComplete ManualDial = - new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial manual string", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Meeting Count Fb")] - public JoinDataComplete MeetingCount = - new JoinDataComplete(new JoinData { JoinNumber = 161, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Meeting Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("MicMuteOff")] - public JoinDataComplete MicMuteOff = - new JoinDataComplete(new JoinData { JoinNumber = 172, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Mic Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteOn")] - public JoinDataComplete MicMuteOn = - new JoinDataComplete(new JoinData { JoinNumber = 171, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Mic Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteToggle")] - public JoinDataComplete MicMuteToggle = - new JoinDataComplete(new JoinData { JoinNumber = 173, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Mic Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MinutesBeforeMeetingStart")] - public JoinDataComplete MinutesBeforeMeetingStart = - new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Minutes before meeting start that a meeting is joinable", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("ParticipantCount")] - public JoinDataComplete ParticipantCount = - new JoinDataComplete(new JoinData { JoinNumber = 151, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Participant Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("Schedule")] - public JoinDataComplete Schedule = - new JoinDataComplete(new JoinData { JoinNumber = 102, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Schedule Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("AutoShareWhileInCall")] - public JoinDataComplete SourceShareAutoStart = - new JoinDataComplete(new JoinData { JoinNumber = 203, JoinSpan = 1 }, - new JoinMetadata - { - Description = "When high, will autostart sharing when a call is joined", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareEnd")] - public JoinDataComplete SourceShareEnd = - new JoinDataComplete(new JoinData { JoinNumber = 202, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Stop Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareStart")] - public JoinDataComplete SourceShareStart = - new JoinDataComplete(new JoinData { JoinNumber = 201, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Start Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RecievingContent")] - public JoinDataComplete RecievingContent = - new JoinDataComplete(new JoinData { JoinNumber = 204, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Recieving content from the far end", - JoinType = eJoinType.Digital, - JoinCapabilities = eJoinCapabilities.ToSIMPL - }); - - [JoinName("SelfviewPosition")] - public JoinDataComplete SelfviewPosition = - new JoinDataComplete(new JoinData { JoinNumber = 211, JoinSpan = 1 }, - new JoinMetadata - { - Description = "advance selfview position", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SelfviewPositionFb")] - public JoinDataComplete SelfviewPositionFb = - new JoinDataComplete(new JoinData { JoinNumber = 211, JoinSpan = 1 }, - new JoinMetadata - { - Description = "advance selfview position", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SpeedDialStart")] - public JoinDataComplete SpeedDialStart = - new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 4 }, - new JoinMetadata - { - Description = "Speed Dial", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("UpdateMeetings")] - public JoinDataComplete UpdateMeetings = - new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Update Meetings", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeDown")] - public JoinDataComplete VolumeDown = - new JoinDataComplete(new JoinData { JoinNumber = 175, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeLevel")] - public JoinDataComplete VolumeLevel = - new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Level", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("VolumeMuteOff")] - public JoinDataComplete VolumeMuteOff = - new JoinDataComplete(new JoinData { JoinNumber = 177, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteOn")] - public JoinDataComplete VolumeMuteOn = - new JoinDataComplete(new JoinData { JoinNumber = 176, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteToggle")] - public JoinDataComplete VolumeMuteToggle = - new JoinDataComplete(new JoinData { JoinNumber = 178, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeUp")] - public JoinDataComplete VolumeUp = - new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialPhoneCall")] - public JoinDataComplete DialPhone = - new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial Phone", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("PhoneHookState")] - public JoinDataComplete PhoneHookState = - new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial Phone", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("EndPhoneCall")] - public JoinDataComplete HangUpPhone = - new JoinDataComplete(new JoinData { JoinNumber = 73, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Hang Up PHone", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("PhoneString")] - public JoinDataComplete PhoneDialString = - new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Phone Dial String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - public VideoCodecControllerJoinMap(uint joinStart) - : base(joinStart, typeof(VideoCodecControllerJoinMap)) - { - } - - public VideoCodecControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } - } + public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced + { + #region Digital + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Device is Online", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("1")] + public JoinDataComplete Dtmf1 = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 1", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("2")] + public JoinDataComplete Dtmf2 = new JoinDataComplete( + new JoinData + { + JoinNumber = 12, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 2", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("3")] + public JoinDataComplete Dtmf3 = new JoinDataComplete( + new JoinData + { + JoinNumber = 13, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 3", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("4")] + public JoinDataComplete Dtmf4 = new JoinDataComplete( + new JoinData + { + JoinNumber = 14, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 4", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("5")] + public JoinDataComplete Dtmf5 = new JoinDataComplete( + new JoinData + { + JoinNumber = 15, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 5", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("6")] + public JoinDataComplete Dtmf6 = new JoinDataComplete( + new JoinData + { + JoinNumber = 16, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 6", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("7")] + public JoinDataComplete Dtmf7 = new JoinDataComplete( + new JoinData + { + JoinNumber = 17, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 7", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("8")] + public JoinDataComplete Dtmf8 = new JoinDataComplete( + new JoinData + { + JoinNumber = 18, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("9")] + public JoinDataComplete Dtmf9 = new JoinDataComplete( + new JoinData + { + JoinNumber = 19, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 9", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("0")] + public JoinDataComplete Dtmf0 = new JoinDataComplete( + new JoinData + { + JoinNumber = 20, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF 0", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("*")] + public JoinDataComplete DtmfStar = new JoinDataComplete( + new JoinData + { + JoinNumber = 21, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF *", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("#")] + public JoinDataComplete DtmfPound = new JoinDataComplete( + new JoinData + { + JoinNumber = 22, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF #", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndCall")] + public JoinDataComplete EndCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 24, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Hang Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HookState")] + public JoinDataComplete HookState = new JoinDataComplete( + new JoinData + { + JoinNumber = 31, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Hook State", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SpeedDialStart")] + public JoinDataComplete SpeedDialStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 41, + JoinSpan = 4 + }, + new JoinMetadata + { + Description = "Speed Dial", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCall")] + public JoinDataComplete IncomingCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 50, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingAnswer")] + public JoinDataComplete IncomingAnswer = new JoinDataComplete( + new JoinData + { + JoinNumber = 51, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Answer Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingReject")] + public JoinDataComplete IncomingReject = new JoinDataComplete( + new JoinData + { + JoinNumber = 52, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reject Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ManualDial")] + public JoinDataComplete ManualDial = new JoinDataComplete( + new JoinData + { + JoinNumber = 71, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial manual string", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialPhoneCall")] + public JoinDataComplete DialPhone = new JoinDataComplete( + new JoinData + { + JoinNumber = 72, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PhoneHookState")] + public JoinDataComplete PhoneHookState = new JoinDataComplete( + new JoinData + { + JoinNumber = 72, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndPhoneCall")] + public JoinDataComplete HangUpPhone = new JoinDataComplete( + new JoinData + { + JoinNumber = 73, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Hang Up PHone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectorySearchBusy")] + public JoinDataComplete DirectorySearchBusy = new JoinDataComplete( + new JoinData + { + JoinNumber = 100, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Search Busy FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryEntryIsContact")] + public JoinDataComplete DirectoryEntryIsContact = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Selected Entry Is Contact FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryLineSelected")] + public JoinDataComplete DirectoryLineSelected = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Line Selected FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryIsRoot")] + public JoinDataComplete DirectoryIsRoot = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory is on Root FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryHasChanged")] + public JoinDataComplete DirectoryHasChanged = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory has changed FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryRoot")] + public JoinDataComplete DirectoryRoot = new JoinDataComplete( + new JoinData + { + JoinNumber = 104, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Go to Directory Root", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryFolderBack")] + public JoinDataComplete DirectoryFolderBack = new JoinDataComplete( + new JoinData + { + JoinNumber = 105, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Go back one directory level", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDialSelectedLine")] + public JoinDataComplete DirectoryDialSelectedLine = new JoinDataComplete( + new JoinData + { + JoinNumber = 106, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial selected directory line", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("CameraTiltUp")] + public JoinDataComplete CameraTiltUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 111, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Tilt Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltDown")] + public JoinDataComplete CameraTiltDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 112, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Tilt Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanLeft")] + public JoinDataComplete CameraPanLeft = new JoinDataComplete( + new JoinData + { + JoinNumber = 113, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Pan Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanRight")] + public JoinDataComplete CameraPanRight = new JoinDataComplete( + new JoinData + { + JoinNumber = 114, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Pan Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomIn")] + public JoinDataComplete CameraZoomIn = new JoinDataComplete( + new JoinData + { + JoinNumber = 115, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomOut")] + public JoinDataComplete CameraZoomOut = new JoinDataComplete( + new JoinData + { + JoinNumber = 116, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPresetSave")] + public JoinDataComplete CameraPresetSave = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Save Selected Preset", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeAuto")] + public JoinDataComplete CameraModeAuto = new JoinDataComplete( + new JoinData + { + JoinNumber = 131, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Auto", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeManual")] + public JoinDataComplete CameraModeManual = new JoinDataComplete( + new JoinData + { + JoinNumber = 132, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Manual", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeOff")] + public JoinDataComplete CameraModeOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 133, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSelfView")] + public JoinDataComplete CameraSelfView = new JoinDataComplete( + new JoinData + { + JoinNumber = 141, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Self View Toggle/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraLayout")] + public JoinDataComplete CameraLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Layout Toggle", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsAutoMode")] + public JoinDataComplete CameraSupportsAutoMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 143, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Supports Auto Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsOffMode")] + public JoinDataComplete CameraSupportsOffMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 144, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Supports Off Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("UpdateMeetings")] + public JoinDataComplete UpdateMeetings = new JoinDataComplete( + new JoinData + { + JoinNumber = 160, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Update Meetings", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting1")] + public JoinDataComplete DialMeeting1 = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join first meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting2")] + public JoinDataComplete DialMeeting2 = new JoinDataComplete( + new JoinData + { + JoinNumber = 162, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join second meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting3")] + public JoinDataComplete DialMeeting3 = new JoinDataComplete( + new JoinData + { + JoinNumber = 163, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join third meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOn")] + public JoinDataComplete MicMuteOn = new JoinDataComplete( + new JoinData + { + JoinNumber = 171, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOff")] + public JoinDataComplete MicMuteOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 172, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteToggle")] + public JoinDataComplete MicMuteToggle = new JoinDataComplete( + new JoinData + { + JoinNumber = 173, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeUp")] + public JoinDataComplete VolumeUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 174, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeDown")] + public JoinDataComplete VolumeDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 175, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOn")] + public JoinDataComplete VolumeMuteOn = new JoinDataComplete( + new JoinData + { + JoinNumber = 176, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOff")] + public JoinDataComplete VolumeMuteOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 177, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteToggle")] + public JoinDataComplete VolumeMuteToggle = new JoinDataComplete( + new JoinData + { + JoinNumber = 178, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareStart")] + public JoinDataComplete SourceShareStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 201, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Start Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareEnd")] + public JoinDataComplete SourceShareEnd = new JoinDataComplete( + new JoinData + { + JoinNumber = 202, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Stop Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("AutoShareWhileInCall")] + public JoinDataComplete SourceShareAutoStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 203, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "When high, will autostart sharing when a call is joined", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RecievingContent")] + public JoinDataComplete RecievingContent = new JoinDataComplete( + new JoinData + { + JoinNumber = 204, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Recieving content from the far end", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToSIMPL + }); + + [JoinName("SelfviewPosition")] + public JoinDataComplete SelfviewPosition = new JoinDataComplete( + new JoinData + { + JoinNumber = 211, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + #endregion + + + + #region Analog + + [JoinName("MinutesBeforeMeetingStart")] + public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 41, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Minutes before meeting start that a meeting is joinable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraNumberSelect")] + public JoinDataComplete CameraNumberSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 60, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Number Select/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectoryRowCount")] + public JoinDataComplete DirectoryRowCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Row Count FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectorySelectRow")] + public JoinDataComplete DirectorySelectRow = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Select Row", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraPresetSelect")] + public JoinDataComplete CameraPresetSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Preset Select", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ParticipantCount")] + public JoinDataComplete ParticipantCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 151, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Participant Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("Meeting Count Fb")] + public JoinDataComplete MeetingCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Meeting Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("VolumeLevel")] + public JoinDataComplete VolumeLevel = new JoinDataComplete( + new JoinData + { + JoinNumber = 174, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Level", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + #endregion + + + + #region Serials + + [JoinName("CurrentDialString")] + public JoinDataComplete CurrentDialString = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Dial String", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("PhoneString")] + public JoinDataComplete PhoneDialString = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Phone Dial String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentCallName")] + public JoinDataComplete CurrentCallData = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Call Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CallDirection")] + public JoinDataComplete CallDirection = new JoinDataComplete( + new JoinData + { + JoinNumber = 22, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Call Direction", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallName")] + public JoinDataComplete IncomingCallName = new JoinDataComplete( + new JoinData + { + JoinNumber = 51, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallNumber")] + public JoinDataComplete IncomingCallNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 52, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("DirectorySearchString")] + public JoinDataComplete DirectorySearchString = new JoinDataComplete( + new JoinData + { + JoinNumber = 100, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Search String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntries")] + public JoinDataComplete DirectoryEntries = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Entries - XSig, 255 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("Schedule")] + public JoinDataComplete Schedule = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Schedule Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraPresetNames")] + public JoinDataComplete CameraPresetNames = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Preset Names - XSIG, max of 15", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraLayoutStringFb")] + public JoinDataComplete CameraLayoutStringFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 141, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Layout Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentParticipants")] + public JoinDataComplete CurrentParticipants = new JoinDataComplete( + new JoinData + { + JoinNumber = 151, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Current Participants XSig", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentSource")] + public JoinDataComplete CurrentSource = new JoinDataComplete( + new JoinData + { + JoinNumber = 201, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Source", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelfviewPositionFb")] + public JoinDataComplete SelfviewPositionFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 211, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedName")] + public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( + new JoinData + { + JoinNumber = 356, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Entry Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedNumber")] + public JoinDataComplete DirectoryEntrySelectedNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 357, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Entry Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectorySelectedFolderName")] + public JoinDataComplete DirectorySelectedFolderName = new JoinDataComplete( + new JoinData + { + JoinNumber = 358, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Folder Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion + + public VideoCodecControllerJoinMap(uint joinStart) + : base(joinStart, typeof(VideoCodecControllerJoinMap)) + { + } + + public VideoCodecControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } } namespace PepperDash_Essentials_Core.Bridges.JoinMaps { - [Obsolete("Use PepperDash.Essentials.Core.Bridges.JoinMaps")] - public class VideoCodecControllerJoinMap :JoinMapBaseAdvanced - { - - #region Status - - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = - new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Device is Online", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - #endregion - - [JoinName("CallDirection")] - public JoinDataComplete CallDirection = - new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Call Direction", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraLayout")] - public JoinDataComplete CameraLayout = - new JoinDataComplete(new JoinData { JoinNumber = 142, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Layout Toggle", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraLayoutStringFb")] - public JoinDataComplete CameraLayoutStringFb = - new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Layout Fb", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraModeAuto")] - public JoinDataComplete CameraModeAuto = - new JoinDataComplete(new JoinData { JoinNumber = 131, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Mode Auto", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeManual")] - public JoinDataComplete CameraModeManual = - new JoinDataComplete(new JoinData { JoinNumber = 132, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Mode Manual", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeOff")] - public JoinDataComplete CameraModeOff = - new JoinDataComplete(new JoinData { JoinNumber = 133, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Mode Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraNumberSelect")] - public JoinDataComplete CameraNumberSelect = - new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Number Select/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraPanLeft")] - public JoinDataComplete CameraPanLeft = - new JoinDataComplete(new JoinData { JoinNumber = 113, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Pan Left", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPanRight")] - public JoinDataComplete CameraPanRight = - new JoinDataComplete(new JoinData { JoinNumber = 114, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Pan Right", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPresetNames")] - public JoinDataComplete CameraPresetNames = - new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Preset Names - XSIG, max of 15", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraPresetSelect")] - public JoinDataComplete CameraPresetSelect = - new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Preset Select", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraPresetSave")] - public JoinDataComplete CameraPresetSave = - new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Save Selected Preset", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSelfView")] - public JoinDataComplete CameraSelfView = - new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Self View Toggle/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsAutoMode")] - public JoinDataComplete CameraSupportsAutoMode = - new JoinDataComplete(new JoinData { JoinNumber = 143, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Supports Auto Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsOffMode")] - public JoinDataComplete CameraSupportsOffMode = - new JoinDataComplete(new JoinData { JoinNumber = 144, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Supports Off Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltDown")] - public JoinDataComplete CameraTiltDown = - new JoinDataComplete(new JoinData { JoinNumber = 112, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Tilt Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltUp")] - public JoinDataComplete CameraTiltUp = - new JoinDataComplete(new JoinData { JoinNumber = 111, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Tilt Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomIn")] - public JoinDataComplete CameraZoomIn = - new JoinDataComplete(new JoinData { JoinNumber = 115, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Zoom In", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomOut")] - public JoinDataComplete CameraZoomOut = - new JoinDataComplete(new JoinData { JoinNumber = 116, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CurrentCallName")] - public JoinDataComplete CurrentCallData = - new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Call Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentDialString")] - public JoinDataComplete CurrentDialString = - new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Dial String", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentParticipants")] - public JoinDataComplete CurrentParticipants = - new JoinDataComplete(new JoinData { JoinNumber = 151, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Participants XSig", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentSource")] - public JoinDataComplete CurrentSource = - new JoinDataComplete(new JoinData { JoinNumber = 201, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Source", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DialMeeting1")] - public JoinDataComplete DialMeeting1 = - new JoinDataComplete(new JoinData { JoinNumber = 161, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Join first meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting2")] - public JoinDataComplete DialMeeting2 = - new JoinDataComplete(new JoinData { JoinNumber = 162, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Join second meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting3")] - public JoinDataComplete DialMeeting3 = - new JoinDataComplete(new JoinData { JoinNumber = 163, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Join third meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryDialSelectedLine")] - public JoinDataComplete DirectoryDialSelectedLine = - new JoinDataComplete(new JoinData { JoinNumber = 106, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial selected directory line", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryEntries")] - public JoinDataComplete DirectoryEntries = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Entries - XSig, 255 entries", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntryIsContact")] - public JoinDataComplete DirectoryEntryIsContact = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Selected Entry Is Contact FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryEntrySelectedName")] - public JoinDataComplete DirectoryEntrySelectedName = - new JoinDataComplete(new JoinData { JoinNumber = 356, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Selected Directory Entry Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntrySelectedNumber")] - public JoinDataComplete DirectoryEntrySelectedNumber = - new JoinDataComplete(new JoinData { JoinNumber = 357, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Selected Directory Entry Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryFolderBack")] - public JoinDataComplete DirectoryFolderBack = - new JoinDataComplete(new JoinData { JoinNumber = 105, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Go back one directory level", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryHasChanged")] - public JoinDataComplete DirectoryHasChanged = - new JoinDataComplete(new JoinData { JoinNumber = 103, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory has changed FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryIsRoot")] - public JoinDataComplete DirectoryIsRoot = - new JoinDataComplete(new JoinData { JoinNumber = 102, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory is on Root FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryLineSelected")] - public JoinDataComplete DirectoryLineSelected = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Line Selected FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryRoot")] - public JoinDataComplete DirectoryRoot = - new JoinDataComplete(new JoinData { JoinNumber = 104, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Go to Directory Root", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryRowCount")] - public JoinDataComplete DirectoryRowCount = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Row Count FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectorySearchBusy")] - public JoinDataComplete DirectorySearchBusy = - new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Search Busy FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectorySearchString")] - public JoinDataComplete DirectorySearchString = - new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Search String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectorySelectRow")] - public JoinDataComplete DirectorySelectRow = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Select Row", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectorySelectedFolderName")] - public JoinDataComplete DirectorySelectedFolderName = - new JoinDataComplete(new JoinData { JoinNumber = 358, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Selected Directory Folder Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("0")] - public JoinDataComplete Dtmf0 = - new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 0", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("1")] - public JoinDataComplete Dtmf1 = - new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 1", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("2")] - public JoinDataComplete Dtmf2 = - new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 2", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("3")] - public JoinDataComplete Dtmf3 = - new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 3", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("4")] - public JoinDataComplete Dtmf4 = - new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 4", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("5")] - public JoinDataComplete Dtmf5 = - new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 5", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("6")] - public JoinDataComplete Dtmf6 = - new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 6", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("7")] - public JoinDataComplete Dtmf7 = - new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 7", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("8")] - public JoinDataComplete Dtmf8 = - new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 8", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("9")] - public JoinDataComplete Dtmf9 = - new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 9", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("#")] - public JoinDataComplete DtmfPound = - new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF #", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("*")] - public JoinDataComplete DtmfStar = - new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF *", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("EndCall")] - public JoinDataComplete EndCall = - new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Hang Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("HookState")] - public JoinDataComplete HookState = - new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Hook State", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingAnswer")] - public JoinDataComplete IncomingAnswer = - new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Answer Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCall")] - public JoinDataComplete IncomingCall = - new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Incoming Call", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCallName")] - public JoinDataComplete IncomingCallName = - new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Incoming Call Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallNumber")] - public JoinDataComplete IncomingCallNumber = - new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Incoming Call Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingReject")] - public JoinDataComplete IncomingReject = - new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Reject Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - - [JoinName("ManualDial")] - public JoinDataComplete ManualDial = - new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial manual string", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Meeting Count Fb")] - public JoinDataComplete MeetingCount = - new JoinDataComplete(new JoinData { JoinNumber = 161, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Meeting Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("MicMuteOff")] - public JoinDataComplete MicMuteOff = - new JoinDataComplete(new JoinData { JoinNumber = 172, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Mic Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteOn")] - public JoinDataComplete MicMuteOn = - new JoinDataComplete(new JoinData { JoinNumber = 171, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Mic Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteToggle")] - public JoinDataComplete MicMuteToggle = - new JoinDataComplete(new JoinData { JoinNumber = 173, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Mic Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MinutesBeforeMeetingStart")] - public JoinDataComplete MinutesBeforeMeetingStart = - new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Minutes before meeting start that a meeting is joinable", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("ParticipantCount")] - public JoinDataComplete ParticipantCount = - new JoinDataComplete(new JoinData { JoinNumber = 151, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Participant Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("Schedule")] - public JoinDataComplete Schedule = - new JoinDataComplete(new JoinData { JoinNumber = 102, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Schedule Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("AutoShareWhileInCall")] - public JoinDataComplete SourceShareAutoStart = - new JoinDataComplete(new JoinData { JoinNumber = 203, JoinSpan = 1 }, - new JoinMetadata - { - Description = "When high, will autostart sharing when a call is joined", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareEnd")] - public JoinDataComplete SourceShareEnd = - new JoinDataComplete(new JoinData { JoinNumber = 202, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Stop Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareStart")] - public JoinDataComplete SourceShareStart = - new JoinDataComplete(new JoinData { JoinNumber = 201, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Start Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RecievingContent")] - public JoinDataComplete RecievingContent = - new JoinDataComplete(new JoinData { JoinNumber = 204, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Recieving content from the far end", - JoinType = eJoinType.Digital, - JoinCapabilities = eJoinCapabilities.ToSIMPL - }); - - [JoinName("SelfviewPosition")] - public JoinDataComplete SelfviewPosition = - new JoinDataComplete(new JoinData { JoinNumber = 211, JoinSpan = 1 }, - new JoinMetadata - { - Description = "advance selfview position", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SelfviewPositionFb")] - public JoinDataComplete SelfviewPositionFb = - new JoinDataComplete(new JoinData { JoinNumber = 211, JoinSpan = 1 }, - new JoinMetadata - { - Description = "advance selfview position", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SpeedDialStart")] - public JoinDataComplete SpeedDialStart = - new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 4 }, - new JoinMetadata - { - Description = "Speed Dial", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("UpdateMeetings")] - public JoinDataComplete UpdateMeetings = - new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Update Meetings", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeDown")] - public JoinDataComplete VolumeDown = - new JoinDataComplete(new JoinData { JoinNumber = 175, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeLevel")] - public JoinDataComplete VolumeLevel = - new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Level", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("VolumeMuteOff")] - public JoinDataComplete VolumeMuteOff = - new JoinDataComplete(new JoinData { JoinNumber = 177, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteOn")] - public JoinDataComplete VolumeMuteOn = - new JoinDataComplete(new JoinData { JoinNumber = 176, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteToggle")] - public JoinDataComplete VolumeMuteToggle = - new JoinDataComplete(new JoinData { JoinNumber = 178, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeUp")] - public JoinDataComplete VolumeUp = - new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialPhoneCall")] - public JoinDataComplete DialPhone = - new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial Phone", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("PhoneHookState")] - public JoinDataComplete PhoneHookState = - new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial Phone", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("EndPhoneCall")] - public JoinDataComplete HangUpPhone = - new JoinDataComplete(new JoinData { JoinNumber = 73, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Hang Up PHone", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("PhoneString")] - public JoinDataComplete PhoneDialString = - new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Phone Dial String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - public VideoCodecControllerJoinMap(uint joinStart) - : base(joinStart, typeof(VideoCodecControllerJoinMap)) - { - } - - public VideoCodecControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } - } - } + [Obsolete("Use PepperDash.Essentials.Core.Bridges.JoinMaps")] + public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced + { + + #region Status + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = + new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Device is Online", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + #endregion + + [JoinName("CallDirection")] + public JoinDataComplete CallDirection = + new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Current Call Direction", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraLayout")] + public JoinDataComplete CameraLayout = + new JoinDataComplete(new JoinData { JoinNumber = 142, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Layout Toggle", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraLayoutStringFb")] + public JoinDataComplete CameraLayoutStringFb = + new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Current Layout Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraModeAuto")] + public JoinDataComplete CameraModeAuto = + new JoinDataComplete(new JoinData { JoinNumber = 131, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Mode Auto", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeManual")] + public JoinDataComplete CameraModeManual = + new JoinDataComplete(new JoinData { JoinNumber = 132, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Mode Manual", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeOff")] + public JoinDataComplete CameraModeOff = + new JoinDataComplete(new JoinData { JoinNumber = 133, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Mode Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraNumberSelect")] + public JoinDataComplete CameraNumberSelect = + new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Number Select/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraPanLeft")] + public JoinDataComplete CameraPanLeft = + new JoinDataComplete(new JoinData { JoinNumber = 113, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Pan Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanRight")] + public JoinDataComplete CameraPanRight = + new JoinDataComplete(new JoinData { JoinNumber = 114, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Pan Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPresetNames")] + public JoinDataComplete CameraPresetNames = + new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Preset Names - XSIG, max of 15", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraPresetSelect")] + public JoinDataComplete CameraPresetSelect = + new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Preset Select", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraPresetSave")] + public JoinDataComplete CameraPresetSave = + new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Save Selected Preset", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSelfView")] + public JoinDataComplete CameraSelfView = + new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Self View Toggle/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsAutoMode")] + public JoinDataComplete CameraSupportsAutoMode = + new JoinDataComplete(new JoinData { JoinNumber = 143, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Supports Auto Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsOffMode")] + public JoinDataComplete CameraSupportsOffMode = + new JoinDataComplete(new JoinData { JoinNumber = 144, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Supports Off Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltDown")] + public JoinDataComplete CameraTiltDown = + new JoinDataComplete(new JoinData { JoinNumber = 112, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Tilt Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltUp")] + public JoinDataComplete CameraTiltUp = + new JoinDataComplete(new JoinData { JoinNumber = 111, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Tilt Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomIn")] + public JoinDataComplete CameraZoomIn = + new JoinDataComplete(new JoinData { JoinNumber = 115, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomOut")] + public JoinDataComplete CameraZoomOut = + new JoinDataComplete(new JoinData { JoinNumber = 116, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CurrentCallName")] + public JoinDataComplete CurrentCallData = + new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Current Call Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentDialString")] + public JoinDataComplete CurrentDialString = + new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Current Dial String", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentParticipants")] + public JoinDataComplete CurrentParticipants = + new JoinDataComplete(new JoinData { JoinNumber = 151, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Participants XSig", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentSource")] + public JoinDataComplete CurrentSource = + new JoinDataComplete(new JoinData { JoinNumber = 201, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Current Source", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DialMeeting1")] + public JoinDataComplete DialMeeting1 = + new JoinDataComplete(new JoinData { JoinNumber = 161, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Join first meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting2")] + public JoinDataComplete DialMeeting2 = + new JoinDataComplete(new JoinData { JoinNumber = 162, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Join second meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting3")] + public JoinDataComplete DialMeeting3 = + new JoinDataComplete(new JoinData { JoinNumber = 163, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Join third meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDialSelectedLine")] + public JoinDataComplete DirectoryDialSelectedLine = + new JoinDataComplete(new JoinData { JoinNumber = 106, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Dial selected directory line", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryEntries")] + public JoinDataComplete DirectoryEntries = + new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Directory Entries - XSig, 255 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntryIsContact")] + public JoinDataComplete DirectoryEntryIsContact = + new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Directory Selected Entry Is Contact FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryEntrySelectedName")] + public JoinDataComplete DirectoryEntrySelectedName = + new JoinDataComplete(new JoinData { JoinNumber = 356, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Selected Directory Entry Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedNumber")] + public JoinDataComplete DirectoryEntrySelectedNumber = + new JoinDataComplete(new JoinData { JoinNumber = 357, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Selected Directory Entry Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryFolderBack")] + public JoinDataComplete DirectoryFolderBack = + new JoinDataComplete(new JoinData { JoinNumber = 105, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Go back one directory level", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryHasChanged")] + public JoinDataComplete DirectoryHasChanged = + new JoinDataComplete(new JoinData { JoinNumber = 103, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Directory has changed FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryIsRoot")] + public JoinDataComplete DirectoryIsRoot = + new JoinDataComplete(new JoinData { JoinNumber = 102, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Directory is on Root FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryLineSelected")] + public JoinDataComplete DirectoryLineSelected = + new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Directory Line Selected FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryRoot")] + public JoinDataComplete DirectoryRoot = + new JoinDataComplete(new JoinData { JoinNumber = 104, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Go to Directory Root", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryRowCount")] + public JoinDataComplete DirectoryRowCount = + new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Directory Row Count FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectorySearchBusy")] + public JoinDataComplete DirectorySearchBusy = + new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Directory Search Busy FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectorySearchString")] + public JoinDataComplete DirectorySearchString = + new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Directory Search String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectorySelectRow")] + public JoinDataComplete DirectorySelectRow = + new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Directory Select Row", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectorySelectedFolderName")] + public JoinDataComplete DirectorySelectedFolderName = + new JoinDataComplete(new JoinData { JoinNumber = 358, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Selected Directory Folder Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("0")] + public JoinDataComplete Dtmf0 = + new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 0", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("1")] + public JoinDataComplete Dtmf1 = + new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 1", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("2")] + public JoinDataComplete Dtmf2 = + new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 2", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("3")] + public JoinDataComplete Dtmf3 = + new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 3", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("4")] + public JoinDataComplete Dtmf4 = + new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 4", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("5")] + public JoinDataComplete Dtmf5 = + new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 5", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("6")] + public JoinDataComplete Dtmf6 = + new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 6", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("7")] + public JoinDataComplete Dtmf7 = + new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 7", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("8")] + public JoinDataComplete Dtmf8 = + new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("9")] + public JoinDataComplete Dtmf9 = + new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF 9", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("#")] + public JoinDataComplete DtmfPound = + new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF #", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("*")] + public JoinDataComplete DtmfStar = + new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DTMF *", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndCall")] + public JoinDataComplete EndCall = + new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Hang Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HookState")] + public JoinDataComplete HookState = + new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Current Hook State", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingAnswer")] + public JoinDataComplete IncomingAnswer = + new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Answer Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCall")] + public JoinDataComplete IncomingCall = + new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCallName")] + public JoinDataComplete IncomingCallName = + new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Incoming Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallNumber")] + public JoinDataComplete IncomingCallNumber = + new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Incoming Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingReject")] + public JoinDataComplete IncomingReject = + new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Reject Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("ManualDial")] + public JoinDataComplete ManualDial = + new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Dial manual string", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Meeting Count Fb")] + public JoinDataComplete MeetingCount = + new JoinDataComplete(new JoinData { JoinNumber = 161, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Meeting Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("MicMuteOff")] + public JoinDataComplete MicMuteOff = + new JoinDataComplete(new JoinData { JoinNumber = 172, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Mic Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOn")] + public JoinDataComplete MicMuteOn = + new JoinDataComplete(new JoinData { JoinNumber = 171, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Mic Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteToggle")] + public JoinDataComplete MicMuteToggle = + new JoinDataComplete(new JoinData { JoinNumber = 173, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Mic Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MinutesBeforeMeetingStart")] + public JoinDataComplete MinutesBeforeMeetingStart = + new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Minutes before meeting start that a meeting is joinable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ParticipantCount")] + public JoinDataComplete ParticipantCount = + new JoinDataComplete(new JoinData { JoinNumber = 151, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Current Participant Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("Schedule")] + public JoinDataComplete Schedule = + new JoinDataComplete(new JoinData { JoinNumber = 102, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Schedule Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("AutoShareWhileInCall")] + public JoinDataComplete SourceShareAutoStart = + new JoinDataComplete(new JoinData { JoinNumber = 203, JoinSpan = 1 }, + new JoinMetadata + { + Description = "When high, will autostart sharing when a call is joined", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareEnd")] + public JoinDataComplete SourceShareEnd = + new JoinDataComplete(new JoinData { JoinNumber = 202, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Stop Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareStart")] + public JoinDataComplete SourceShareStart = + new JoinDataComplete(new JoinData { JoinNumber = 201, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Start Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RecievingContent")] + public JoinDataComplete RecievingContent = + new JoinDataComplete(new JoinData { JoinNumber = 204, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Recieving content from the far end", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToSIMPL + }); + + [JoinName("SelfviewPosition")] + public JoinDataComplete SelfviewPosition = + new JoinDataComplete(new JoinData { JoinNumber = 211, JoinSpan = 1 }, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SelfviewPositionFb")] + public JoinDataComplete SelfviewPositionFb = + new JoinDataComplete(new JoinData { JoinNumber = 211, JoinSpan = 1 }, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SpeedDialStart")] + public JoinDataComplete SpeedDialStart = + new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 4 }, + new JoinMetadata + { + Description = "Speed Dial", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("UpdateMeetings")] + public JoinDataComplete UpdateMeetings = + new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Update Meetings", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeDown")] + public JoinDataComplete VolumeDown = + new JoinDataComplete(new JoinData { JoinNumber = 175, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeLevel")] + public JoinDataComplete VolumeLevel = + new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Level", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("VolumeMuteOff")] + public JoinDataComplete VolumeMuteOff = + new JoinDataComplete(new JoinData { JoinNumber = 177, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOn")] + public JoinDataComplete VolumeMuteOn = + new JoinDataComplete(new JoinData { JoinNumber = 176, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteToggle")] + public JoinDataComplete VolumeMuteToggle = + new JoinDataComplete(new JoinData { JoinNumber = 178, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeUp")] + public JoinDataComplete VolumeUp = + new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Volume Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialPhoneCall")] + public JoinDataComplete DialPhone = + new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PhoneHookState")] + public JoinDataComplete PhoneHookState = + new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Dial Phone", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EndPhoneCall")] + public JoinDataComplete HangUpPhone = + new JoinDataComplete(new JoinData { JoinNumber = 73, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Hang Up PHone", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PhoneString")] + public JoinDataComplete PhoneDialString = + new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Phone Dial String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + public VideoCodecControllerJoinMap(uint joinStart) + : base(joinStart, typeof(VideoCodecControllerJoinMap)) + { + } + + public VideoCodecControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} 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 8ba3d139..00787a69 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 @@ -27,8 +27,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { event EventHandler AvailableLayoutsChanged; - 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 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; } 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 1cdb6bc7..a693bb12 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,14 +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 - /// - /// - /// - /// - /// - /// + /// + /// Use this method when using a plain VideoCodecControllerJoinMap + /// + /// + /// + /// + /// + /// protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { @@ -296,144 +296,144 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec bridge.AddJoinMap(Key, joinMap); } - LinkVideoCodecToApi(codec, trilist, joinMap); + 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")); + /// + /// 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); + LinkVideoCodecDtmfToApi(trilist, joinMap); - LinkVideoCodecCallControlsToApi(trilist, joinMap); + LinkVideoCodecCallControlsToApi(trilist, joinMap); - LinkVideoCodecContentSharingToApi(trilist, joinMap); + LinkVideoCodecContentSharingToApi(trilist, joinMap); - LinkVideoCodecPrivacyToApi(trilist, joinMap); + LinkVideoCodecPrivacyToApi(trilist, joinMap); - LinkVideoCodecVolumeToApi(trilist, joinMap); + LinkVideoCodecVolumeToApi(trilist, joinMap); - if (codec is ICommunicationMonitor) - { - LinkVideoCodecCommMonitorToApi(codec as ICommunicationMonitor, 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 IHasCodecCameras) + { + LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); + } - if (codec is IHasCodecSelfView) - { - LinkVideoCodecSelfviewToApi(codec as IHasCodecSelfView, 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 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 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 IHasCodecLayouts) + { + LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap); + } - if (codec is IHasSelfviewPosition) - { - LinkVideoCodecSelfviewPositionToApi(codec as IHasSelfviewPosition, 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 IHasDirectory) + { + LinkVideoCodecDirectoryToApi(codec as IHasDirectory, trilist, joinMap); + } - if (codec is IHasScheduleAwareness) - { - LinkVideoCodecScheduleToApi(codec as IHasScheduleAwareness, 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 IHasParticipants) + { + LinkVideoCodecParticipantsToApi(codec as IHasParticipants, trilist, joinMap); + } - if (codec is IHasFarEndContentStatus) - { - (codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]); - } + if (codec is IHasFarEndContentStatus) + { + (codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]); + } - if (codec is IHasPhoneDialing) - { - LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); - } + if (codec is IHasPhoneDialing) + { + LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); + } - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; - if (codec is IHasDirectory) - { - (codec as IHasDirectory).SetCurrentDirectoryToRoot(); - } + if (codec is IHasDirectory) + { + (codec as IHasDirectory).SetCurrentDirectoryToRoot(); + } - if (codec is IHasScheduleAwareness) - { - (codec as IHasScheduleAwareness).GetSchedule(); - } + if (codec is IHasScheduleAwareness) + { + (codec as IHasScheduleAwareness).GetSchedule(); + } - if (codec is IHasParticipants) - { - UpdateParticipantsXSig((codec as IHasParticipants).Participants.CurrentParticipants); - } + if (codec is IHasParticipants) + { + UpdateParticipantsXSig((codec as IHasParticipants).Participants.CurrentParticipants); + } - if (codec is IHasCameraAutoMode) - { - trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); + if (codec is IHasCameraAutoMode) + { + trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); - (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); - } + (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); + } - if (codec is IHasCodecSelfView) - { - (codec as IHasCodecSelfView).SelfviewIsOnFeedback.FireUpdate(); - } + if (codec is IHasCodecSelfView) + { + (codec as IHasCodecSelfView).SelfviewIsOnFeedback.FireUpdate(); + } - if (codec is IHasCameraAutoMode) - { - (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); - } + if (codec is IHasCameraAutoMode) + { + (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); + } - if (codec is IHasCameraOff) - { - (codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate(); - } + if (codec is IHasCameraOff) + { + (codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate(); + } - if (codec is IHasPhoneDialing) - { - (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); - } + if (codec is IHasPhoneDialing) + { + (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); + } - SharingContentIsOnFeedback.FireUpdate(); + SharingContentIsOnFeedback.FireUpdate(); - trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); - trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); - }; - } + trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); + }; + } private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -548,8 +548,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetUshort(joinMap.ParticipantCount.JoinNumber, (ushort)codec.Participants.CurrentParticipants.Count); }; - // TODO: #698 Figure out how to decode xsig data and trigger actions based on values from SIMPL - // trilist.SetStringSigAction(joinMap.CurrentParticipants.JoinNumber, // add method here to decode the xsig info and trigger actions + // TODO: #698 [ ] Figure out how to decode xsig data and trigger actions based on values from SIMPL + // add method here to decode the xsig info and trigger actions + //trilist.SetStringSigAction(joinMap.CurrentParticipants.JoinNumber, DecodeParticipantsXSig); } private string UpdateParticipantsXSig(List currentParticipants) @@ -557,11 +558,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec const int maxParticipants = 50; const int maxDigitals = 7; const int maxStrings = 1; - const int maxAnalogs = 1; - const int offset = maxDigitals + maxStrings; - var digitalIndex = maxStrings * maxParticipants; //15 + const int maxAnalogs = 1; + const int offset = maxDigitals + maxStrings + maxAnalogs; + var digitalIndex = maxStrings + maxAnalogs * maxParticipants; //15 var stringIndex = 0; - var analogIndex = 0; + var analogIndex = 0; var meetingIndex = 0; var tokenArray = new XSigToken[maxParticipants * offset]; @@ -576,47 +577,88 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, participant.CanMuteVideo); tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, participant.CanUnmuteVideo); tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, participant.IsHost); - tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, participant.HandIsRaisedFb); - tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 6, participant.IsPinnedFb); + tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, participant.HandIsRaisedFb); + tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, participant.IsPinnedFb); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, participant.Name); - //analogs - tokenArray[analogIndex] = new XSigAnalogToken(analogIndex + 1, (ushort)participant.ScreenIndexIsPinnedToFb); + //analogs + tokenArray[analogIndex] = new XSigAnalogToken(analogIndex + 1, (ushort)participant.ScreenIndexIsPinnedToFb); digitalIndex += maxDigitals; meetingIndex += offset; stringIndex += maxStrings; - analogIndex += maxAnalogs; + analogIndex += maxAnalogs; } while (meetingIndex < maxParticipants * offset) { - //digitals + //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, false); tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, false); tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, false); - tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, false); - tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, false); + tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, false); + tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, false); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); - //analogs - tokenArray[analogIndex] = new XSigAnalogToken(analogIndex + 1, 0); + //analogs + tokenArray[analogIndex] = new XSigAnalogToken(analogIndex + 1, 0); digitalIndex += maxDigitals; meetingIndex += offset; stringIndex += maxStrings; - analogIndex += maxAnalogs; + analogIndex += maxAnalogs; } return GetXSigString(tokenArray); } + // TODO: #698 [ ] Figure out how to decode xsig data and trigger actions based on values from SIMPL + private void DecodeParticipantsXSig(string xsigData) + { + if (string.IsNullOrEmpty(xsigData)) return; + var bytes = Encoding.GetEncoding(XSigEncoding).GetBytes(xsigData); + using (var xsigStream = new XSigTokenStreamReader(new MemoryStream(bytes))) + { + XSigToken token = null; + while ((token = xsigStream.ReadXSigToken()) != null) + { + switch (token.TokenType) + { + case XSigTokenType.Digital: + { + var data = token as XSigDigitalToken; + if (data == null) return; + Debug.Console(1, this, "xSig Data TokenType: {0} | Index: {1} | Value: {2}", + data.TokenType, data.Index, data.Value.ToString()); + break; + } + case XSigTokenType.Analog: + { + var data = token as XSigAnalogToken; + if (data == null) return; + Debug.Console(1, this, "xSig Data TokenType: {0} | Index: {1} | Value: {2}", + data.TokenType, data.Index, data.Value); + break; + } + case XSigTokenType.Serial: + { + var data = token as XSigSerialToken; + if (data == null) return; + Debug.Console(1, this, "xSig Data TokenType: {0} | Index: {1} | Value: {2}", data.TokenType, data.Index, + data.Value); + break; + } + } + } + } + } + private void LinkVideoCodecContentSharingToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { SharingContentIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SourceShareStart.JoinNumber]); @@ -882,7 +924,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec Debug.Console(1, this, "Call Direction: {0}", args.CallItem.Direction); Debug.Console(1, this, "Call is incoming: {0}", args.CallItem.Direction == eCodecCallDirection.Incoming); - trilist.SetBool(joinMap.IncomingCall.JoinNumber, args.CallItem.Direction == eCodecCallDirection.Incoming && args.CallItem.Status == eCodecCallStatus.Ringing); + trilist.SetBool(joinMap.IncomingCall.JoinNumber, args.CallItem.Direction == eCodecCallDirection.Incoming && args.CallItem.Status == eCodecCallStatus.Ringing); if (args.CallItem.Direction == eCodecCallDirection.Incoming) { 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 a0a8158c..10f5929d 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 @@ -1723,7 +1723,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap) { var layoutsCodec = this as IHasZoomRoomLayouts; - if (layoutsCodec != null) { layoutsCodec.AvailableLayoutsChanged += (o, a) => @@ -1746,7 +1745,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom layoutsCodec.LayoutViewIsOnLastPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnLastPage.JoinNumber]); trilist.SetSigFalseAction(joinMap.LayoutTurnToNextPage.JoinNumber, () => layoutsCodec.LayoutTurnNextPage()); trilist.SetSigFalseAction(joinMap.LayoutTurnToPreviousPage.JoinNumber, () => layoutsCodec.LayoutTurnPreviousPage()); - + trilist.SetSigFalseAction(joinMap.GetAvailableLayouts.JoinNumber, () => layoutsCodec.GetAvailableLayouts()); trilist.SetStringSigAction(joinMap.GetSetCurrentLayout.JoinNumber, (s) => { @@ -1757,22 +1756,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } catch (Exception e) { - Debug.Console(2, this, "Unable to parse '{0}' to zConfiguration.eLayoutStyle: {1}", s, e); + Debug.Console(1, this, "Unable to parse '{0}' to zConfiguration.eLayoutStyle: {1}", s, e); } }); - layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); + layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); } var pinCodec = this as IHasParticipantPinUnpin; + if (pinCodec != null) + { + pinCodec.NumberOfScreensFeedback.LinkInputSig(trilist.UShortInput[joinMap.NumberOfScreens.JoinNumber]); - if (pinCodec != null) - { - pinCodec.NumberOfScreensFeedback.LinkInputSig(trilist.UShortInput[joinMap.NumberOfScreens.JoinNumber]); - - // Set the value of the local property to be used when pinning a participant - trilist.SetUShortSigAction(joinMap.ScreenIndexToPinUserTo.JoinNumber, (u) => ScreenIndexToPinUserTo = u); - } + // Set the value of the local property to be used when pinning a participant + trilist.SetUShortSigAction(joinMap.ScreenIndexToPinUserTo.JoinNumber, (u) => ScreenIndexToPinUserTo = u); + } } public override void ExecuteSwitch(object selector) @@ -2208,7 +2206,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void ComputeAvailableLayouts() { zConfiguration.eLayoutStyle availableLayouts = zConfiguration.eLayoutStyle.None; - // TODO: #697 Compute the avaialble layouts and set the value of AvailableLayouts + // TODO: #697 [ ] Compute the avaialble layouts and set the value of AvailableLayouts // Will need to test and confirm that this logic evaluates correctly if (Status.Layout.can_Switch_Wall_View) { @@ -2257,7 +2255,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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 + // 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)); } 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 index fd0e9a4a..7ceb1ba3 100644 --- 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 @@ -4,188 +4,270 @@ using PepperDash.Essentials.Core.Bridges.JoinMaps; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { - public class ZoomRoomJoinMap : VideoCodecControllerJoinMap - { - // TODO: #697 Set join numbers + public class ZoomRoomJoinMap : VideoCodecControllerJoinMap + { + // TODO: #697 [X] 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 - }); + #region 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("CanSwapContentWithThumbnail")] + public JoinDataComplete CanSwapContentWithThumbnail = new JoinDataComplete( + new JoinData + { + JoinNumber = 206, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "FB Indicates if content can be swapped with thumbnail", + 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("SwapContentWithThumbnail")] + public JoinDataComplete SwapContentWithThumbnail = new JoinDataComplete( + new JoinData + { + JoinNumber = 206, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to swap content with thumbnail. FB reports current state", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + 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("GetAvailableLayouts")] + public JoinDataComplete GetAvailableLayouts = new JoinDataComplete( + new JoinData + { + JoinNumber = 215, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Gets the available layouts. Will update the LayoutXXXXXIsAvailbale signals.", + 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("LayoutIsOnFirstPage")] + public JoinDataComplete LayoutIsOnFirstPage = new JoinDataComplete( + new JoinData + { + JoinNumber = 216, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Indicates if layout is on first page", + 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("LayoutIsOnLastPage")] + public JoinDataComplete LayoutIsOnLastPage = new JoinDataComplete( + new JoinData + { + JoinNumber = 217, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Indicates if layout is on first page", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + 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("LayoutTurnToNextPage")] + public JoinDataComplete LayoutTurnToNextPage = new JoinDataComplete( + new JoinData + { + JoinNumber = 216, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Turns layout view to next page", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); - [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("LayoutTurnToPreviousPage")] + public JoinDataComplete LayoutTurnToPreviousPage = new JoinDataComplete( + new JoinData + { + JoinNumber = 217, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Turns layout view to previous page", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); - [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("LayoutGalleryIsAvailable")] + public JoinDataComplete LayoutGalleryIsAvailable = new JoinDataComplete( + new JoinData + { + JoinNumber = 221, + 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("LayoutSpeakerIsAvailable")] + public JoinDataComplete LayoutSpeakerIsAvailable = new JoinDataComplete( + new JoinData + { + JoinNumber = 222, + 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("LayoutStripIsAvailable")] + public JoinDataComplete LayoutStripIsAvailable = new JoinDataComplete( + new JoinData + { + JoinNumber = 223, + 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 - }); + [JoinName("LayoutShareAllIsAvailable")] + public JoinDataComplete LayoutShareAllIsAvailable = new JoinDataComplete( + new JoinData + { + JoinNumber = 224, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "FB Indicates if layout 'ShareAll' is available", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("ScreenIndexToPinUserTo")] - public JoinDataComplete ScreenIndexToPinUserTo = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Specifies the screen index a participant should be pinned to", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); + [JoinName("ParticipantAudioMuteToggleStart")] + public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 500, + JoinSpan = 100 + }, + new JoinMetadata + { + Description = "Toggles the participant's audio mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("NumberOfScreens")] - public JoinDataComplete NumberOfScreens = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Reports the number of screens connected", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); + [JoinName("ParticipantVideoMuteToggleStart")] + public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 800, + JoinSpan = 100 + }, + new JoinMetadata + { + Description = "Toggles the participant's video mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("ParticipantAudioMuteToggleStart")] - public JoinDataComplete ParticipantAudioMuteToggleStart = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Toggles the participant's audio mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("ParticipantPinToggleStart")] + public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 1100, + JoinSpan = 100 + }, + new JoinMetadata + { + Description = "Toggles the participant's pin status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("ParticipantVideoMuteToggleStart")] - public JoinDataComplete ParticipantVideoMuteToggleStart = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Toggles the participant's video mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + #endregion - [JoinName("ParticipantPinToggleStart")] - public JoinDataComplete ParticipantPinToggleStart = - new JoinDataComplete(new JoinData { JoinNumber = 999, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Toggles the participant's pin status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - public ZoomRoomJoinMap(uint joinStart) - : base(joinStart, typeof(ZoomRoomJoinMap)) - { - } + #region Analog - public ZoomRoomJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } - } + [JoinName("NumberOfScreens")] + public JoinDataComplete NumberOfScreens = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of screens connected", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ScreenIndexToPinUserTo")] + public JoinDataComplete ScreenIndexToPinUserTo = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Specifies the screen index a participant should be pinned to", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + #endregion + + + #region Serials + + [JoinName("GetSetCurrentLayout")] + public JoinDataComplete GetSetCurrentLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 215, + 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 + }); + + #endregion + + public ZoomRoomJoinMap(uint joinStart) + : base(joinStart, typeof(ZoomRoomJoinMap)) + { + } + + public ZoomRoomJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } } \ No newline at end of file From 118bd5a54a5c27562938b21e4a267d4a984258b6 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 11 May 2021 11:19:33 -0500 Subject: [PATCH 16/28] Updates VideoCodecControllerJoinMap.cs to organize joins. Update to VideoCodecBase.cs UpdateParticipantsXSig. --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 1776 ++++++++++------- .../VideoCodec/VideoCodecBase.cs | 6 +- 2 files changed, 1073 insertions(+), 709 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 1b6d9483..53ed852a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -1241,6 +1241,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps #endregion + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof(VideoCodecControllerJoinMap)) { @@ -1260,11 +1261,15 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced { - #region Status + #region Digital [JoinName("IsOnline")] - public JoinDataComplete IsOnline = - new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + public JoinDataComplete IsOnline = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, new JoinMetadata { Description = "Device is Online", @@ -1272,431 +1277,13 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - #endregion - - [JoinName("CallDirection")] - public JoinDataComplete CallDirection = - new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Call Direction", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraLayout")] - public JoinDataComplete CameraLayout = - new JoinDataComplete(new JoinData { JoinNumber = 142, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Layout Toggle", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraLayoutStringFb")] - public JoinDataComplete CameraLayoutStringFb = - new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Layout Fb", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraModeAuto")] - public JoinDataComplete CameraModeAuto = - new JoinDataComplete(new JoinData { JoinNumber = 131, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Mode Auto", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeManual")] - public JoinDataComplete CameraModeManual = - new JoinDataComplete(new JoinData { JoinNumber = 132, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Mode Manual", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeOff")] - public JoinDataComplete CameraModeOff = - new JoinDataComplete(new JoinData { JoinNumber = 133, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Mode Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraNumberSelect")] - public JoinDataComplete CameraNumberSelect = - new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Number Select/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraPanLeft")] - public JoinDataComplete CameraPanLeft = - new JoinDataComplete(new JoinData { JoinNumber = 113, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Pan Left", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPanRight")] - public JoinDataComplete CameraPanRight = - new JoinDataComplete(new JoinData { JoinNumber = 114, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Pan Right", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPresetNames")] - public JoinDataComplete CameraPresetNames = - new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Preset Names - XSIG, max of 15", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraPresetSelect")] - public JoinDataComplete CameraPresetSelect = - new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Preset Select", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CameraPresetSave")] - public JoinDataComplete CameraPresetSave = - new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Save Selected Preset", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSelfView")] - public JoinDataComplete CameraSelfView = - new JoinDataComplete(new JoinData { JoinNumber = 141, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Self View Toggle/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsAutoMode")] - public JoinDataComplete CameraSupportsAutoMode = - new JoinDataComplete(new JoinData { JoinNumber = 143, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Supports Auto Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsOffMode")] - public JoinDataComplete CameraSupportsOffMode = - new JoinDataComplete(new JoinData { JoinNumber = 144, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Supports Off Mode FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltDown")] - public JoinDataComplete CameraTiltDown = - new JoinDataComplete(new JoinData { JoinNumber = 112, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Tilt Down", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltUp")] - public JoinDataComplete CameraTiltUp = - new JoinDataComplete(new JoinData { JoinNumber = 111, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Tilt Up", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomIn")] - public JoinDataComplete CameraZoomIn = - new JoinDataComplete(new JoinData { JoinNumber = 115, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Zoom In", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomOut")] - public JoinDataComplete CameraZoomOut = - new JoinDataComplete(new JoinData { JoinNumber = 116, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CurrentCallName")] - public JoinDataComplete CurrentCallData = - new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Call Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentDialString")] - public JoinDataComplete CurrentDialString = - new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Dial String", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentParticipants")] - public JoinDataComplete CurrentParticipants = - new JoinDataComplete(new JoinData { JoinNumber = 151, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Participants XSig", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentSource")] - public JoinDataComplete CurrentSource = - new JoinDataComplete(new JoinData { JoinNumber = 201, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Source", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DialMeeting1")] - public JoinDataComplete DialMeeting1 = - new JoinDataComplete(new JoinData { JoinNumber = 161, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Join first meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting2")] - public JoinDataComplete DialMeeting2 = - new JoinDataComplete(new JoinData { JoinNumber = 162, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Join second meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialMeeting3")] - public JoinDataComplete DialMeeting3 = - new JoinDataComplete(new JoinData { JoinNumber = 163, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Join third meeting", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryDialSelectedLine")] - public JoinDataComplete DirectoryDialSelectedLine = - new JoinDataComplete(new JoinData { JoinNumber = 106, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial selected directory line", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryEntries")] - public JoinDataComplete DirectoryEntries = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Entries - XSig, 255 entries", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntryIsContact")] - public JoinDataComplete DirectoryEntryIsContact = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Selected Entry Is Contact FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryEntrySelectedName")] - public JoinDataComplete DirectoryEntrySelectedName = - new JoinDataComplete(new JoinData { JoinNumber = 356, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Selected Directory Entry Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntrySelectedNumber")] - public JoinDataComplete DirectoryEntrySelectedNumber = - new JoinDataComplete(new JoinData { JoinNumber = 357, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Selected Directory Entry Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryFolderBack")] - public JoinDataComplete DirectoryFolderBack = - new JoinDataComplete(new JoinData { JoinNumber = 105, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Go back one directory level", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryHasChanged")] - public JoinDataComplete DirectoryHasChanged = - new JoinDataComplete(new JoinData { JoinNumber = 103, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory has changed FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryIsRoot")] - public JoinDataComplete DirectoryIsRoot = - new JoinDataComplete(new JoinData { JoinNumber = 102, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory is on Root FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryLineSelected")] - public JoinDataComplete DirectoryLineSelected = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Line Selected FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryRoot")] - public JoinDataComplete DirectoryRoot = - new JoinDataComplete(new JoinData { JoinNumber = 104, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Go to Directory Root", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryRowCount")] - public JoinDataComplete DirectoryRowCount = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Row Count FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectorySearchBusy")] - public JoinDataComplete DirectorySearchBusy = - new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Search Busy FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectorySearchString")] - public JoinDataComplete DirectorySearchString = - new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Search String", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectorySelectRow")] - public JoinDataComplete DirectorySelectRow = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Directory Select Row", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectorySelectedFolderName")] - public JoinDataComplete DirectorySelectedFolderName = - new JoinDataComplete(new JoinData { JoinNumber = 358, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Selected Directory Folder Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("0")] - public JoinDataComplete Dtmf0 = - new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DTMF 0", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - [JoinName("1")] - public JoinDataComplete Dtmf1 = - new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + public JoinDataComplete Dtmf1 = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF 1", @@ -1705,8 +1292,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("2")] - public JoinDataComplete Dtmf2 = - new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + public JoinDataComplete Dtmf2 = new JoinDataComplete( + new JoinData + { + JoinNumber = 12, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF 2", @@ -1715,8 +1306,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("3")] - public JoinDataComplete Dtmf3 = - new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + public JoinDataComplete Dtmf3 = new JoinDataComplete( + new JoinData + { + JoinNumber = 13, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF 3", @@ -1725,8 +1320,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("4")] - public JoinDataComplete Dtmf4 = - new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + public JoinDataComplete Dtmf4 = new JoinDataComplete( + new JoinData + { + JoinNumber = 14, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF 4", @@ -1735,8 +1334,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("5")] - public JoinDataComplete Dtmf5 = - new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + public JoinDataComplete Dtmf5 = new JoinDataComplete( + new JoinData + { + JoinNumber = 15, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF 5", @@ -1745,8 +1348,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("6")] - public JoinDataComplete Dtmf6 = - new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, + public JoinDataComplete Dtmf6 = new JoinDataComplete( + new JoinData + { + JoinNumber = 16, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF 6", @@ -1755,8 +1362,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("7")] - public JoinDataComplete Dtmf7 = - new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, + public JoinDataComplete Dtmf7 = new JoinDataComplete( + new JoinData + { + JoinNumber = 17, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF 7", @@ -1765,8 +1376,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("8")] - public JoinDataComplete Dtmf8 = - new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, + public JoinDataComplete Dtmf8 = new JoinDataComplete( + new JoinData + { + JoinNumber = 18, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF 8", @@ -1775,8 +1390,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("9")] - public JoinDataComplete Dtmf9 = - new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, + public JoinDataComplete Dtmf9 = new JoinDataComplete( + new JoinData + { + JoinNumber = 19, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF 9", @@ -1784,19 +1403,27 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("#")] - public JoinDataComplete DtmfPound = - new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + [JoinName("0")] + public JoinDataComplete Dtmf0 = new JoinDataComplete( + new JoinData + { + JoinNumber = 20, + JoinSpan = 1 + }, new JoinMetadata { - Description = "DTMF #", + Description = "DTMF 0", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); [JoinName("*")] - public JoinDataComplete DtmfStar = - new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, + public JoinDataComplete DtmfStar = new JoinDataComplete( + new JoinData + { + JoinNumber = 21, + JoinSpan = 1 + }, new JoinMetadata { Description = "DTMF *", @@ -1804,9 +1431,27 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("#")] + public JoinDataComplete DtmfPound = new JoinDataComplete( + new JoinData + { + JoinNumber = 22, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DTMF #", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + [JoinName("EndCall")] - public JoinDataComplete EndCall = - new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, + public JoinDataComplete EndCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 24, + JoinSpan = 1 + }, new JoinMetadata { Description = "Hang Up", @@ -1815,8 +1460,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("HookState")] - public JoinDataComplete HookState = - new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, + public JoinDataComplete HookState = new JoinDataComplete( + new JoinData + { + JoinNumber = 31, + JoinSpan = 1 + }, new JoinMetadata { Description = "Current Hook State", @@ -1824,200 +1473,13 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("IncomingAnswer")] - public JoinDataComplete IncomingAnswer = - new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Answer Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCall")] - public JoinDataComplete IncomingCall = - new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Incoming Call", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCallName")] - public JoinDataComplete IncomingCallName = - new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Incoming Call Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallNumber")] - public JoinDataComplete IncomingCallNumber = - new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Incoming Call Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingReject")] - public JoinDataComplete IncomingReject = - new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Reject Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - - [JoinName("ManualDial")] - public JoinDataComplete ManualDial = - new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Dial manual string", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Meeting Count Fb")] - public JoinDataComplete MeetingCount = - new JoinDataComplete(new JoinData { JoinNumber = 161, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Meeting Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("MicMuteOff")] - public JoinDataComplete MicMuteOff = - new JoinDataComplete(new JoinData { JoinNumber = 172, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Mic Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteOn")] - public JoinDataComplete MicMuteOn = - new JoinDataComplete(new JoinData { JoinNumber = 171, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Mic Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MicMuteToggle")] - public JoinDataComplete MicMuteToggle = - new JoinDataComplete(new JoinData { JoinNumber = 173, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Mic Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MinutesBeforeMeetingStart")] - public JoinDataComplete MinutesBeforeMeetingStart = - new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Minutes before meeting start that a meeting is joinable", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("ParticipantCount")] - public JoinDataComplete ParticipantCount = - new JoinDataComplete(new JoinData { JoinNumber = 151, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Current Participant Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("Schedule")] - public JoinDataComplete Schedule = - new JoinDataComplete(new JoinData { JoinNumber = 102, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Schedule Data - XSIG", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("AutoShareWhileInCall")] - public JoinDataComplete SourceShareAutoStart = - new JoinDataComplete(new JoinData { JoinNumber = 203, JoinSpan = 1 }, - new JoinMetadata - { - Description = "When high, will autostart sharing when a call is joined", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareEnd")] - public JoinDataComplete SourceShareEnd = - new JoinDataComplete(new JoinData { JoinNumber = 202, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Stop Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceShareStart")] - public JoinDataComplete SourceShareStart = - new JoinDataComplete(new JoinData { JoinNumber = 201, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Start Sharing & Feedback", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RecievingContent")] - public JoinDataComplete RecievingContent = - new JoinDataComplete(new JoinData { JoinNumber = 204, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Recieving content from the far end", - JoinType = eJoinType.Digital, - JoinCapabilities = eJoinCapabilities.ToSIMPL - }); - - [JoinName("SelfviewPosition")] - public JoinDataComplete SelfviewPosition = - new JoinDataComplete(new JoinData { JoinNumber = 211, JoinSpan = 1 }, - new JoinMetadata - { - Description = "advance selfview position", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SelfviewPositionFb")] - public JoinDataComplete SelfviewPositionFb = - new JoinDataComplete(new JoinData { JoinNumber = 211, JoinSpan = 1 }, - new JoinMetadata - { - Description = "advance selfview position", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - [JoinName("SpeedDialStart")] - public JoinDataComplete SpeedDialStart = - new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 4 }, + public JoinDataComplete SpeedDialStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 41, + JoinSpan = 4 + }, new JoinMetadata { Description = "Speed Dial", @@ -2025,79 +1487,69 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - [JoinName("UpdateMeetings")] - public JoinDataComplete UpdateMeetings = - new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 1 }, + [JoinName("IncomingCall")] + public JoinDataComplete IncomingCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 50, + JoinSpan = 1 + }, new JoinMetadata { - Description = "Update Meetings", + Description = "Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingAnswer")] + public JoinDataComplete IncomingAnswer = new JoinDataComplete( + new JoinData + { + JoinNumber = 51, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Answer Incoming Call", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("VolumeDown")] - public JoinDataComplete VolumeDown = - new JoinDataComplete(new JoinData { JoinNumber = 175, JoinSpan = 1 }, + [JoinName("IncomingReject")] + public JoinDataComplete IncomingReject = new JoinDataComplete( + new JoinData + { + JoinNumber = 52, + JoinSpan = 1 + }, new JoinMetadata { - Description = "Volume Down", + Description = "Reject Incoming Call", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("VolumeLevel")] - public JoinDataComplete VolumeLevel = - new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, + [JoinName("ManualDial")] + public JoinDataComplete ManualDial = new JoinDataComplete( + new JoinData + { + JoinNumber = 71, + JoinSpan = 1 + }, new JoinMetadata { - Description = "Volume Level", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("VolumeMuteOff")] - public JoinDataComplete VolumeMuteOff = - new JoinDataComplete(new JoinData { JoinNumber = 177, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteOn")] - public JoinDataComplete VolumeMuteOn = - new JoinDataComplete(new JoinData { JoinNumber = 176, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute On", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeMuteToggle")] - public JoinDataComplete VolumeMuteToggle = - new JoinDataComplete(new JoinData { JoinNumber = 178, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Mute Toggle", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("VolumeUp")] - public JoinDataComplete VolumeUp = - new JoinDataComplete(new JoinData { JoinNumber = 174, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Volume Up", + Description = "Dial manual string", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); [JoinName("DialPhoneCall")] - public JoinDataComplete DialPhone = - new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, + public JoinDataComplete DialPhone = new JoinDataComplete( + new JoinData + { + JoinNumber = 72, + JoinSpan = 1 + }, new JoinMetadata { Description = "Dial Phone", @@ -2106,8 +1558,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("PhoneHookState")] - public JoinDataComplete PhoneHookState = - new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 }, + public JoinDataComplete PhoneHookState = new JoinDataComplete( + new JoinData + { + JoinNumber = 72, + JoinSpan = 1 + }, new JoinMetadata { Description = "Dial Phone", @@ -2116,8 +1572,12 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps }); [JoinName("EndPhoneCall")] - public JoinDataComplete HangUpPhone = - new JoinDataComplete(new JoinData { JoinNumber = 73, JoinSpan = 1 }, + public JoinDataComplete HangUpPhone = new JoinDataComplete( + new JoinData + { + JoinNumber = 73, + JoinSpan = 1 + }, new JoinMetadata { Description = "Hang Up PHone", @@ -2125,9 +1585,699 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); + [JoinName("DirectorySearchBusy")] + public JoinDataComplete DirectorySearchBusy = new JoinDataComplete( + new JoinData + { + JoinNumber = 100, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Search Busy FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryEntryIsContact")] + public JoinDataComplete DirectoryEntryIsContact = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Selected Entry Is Contact FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryLineSelected")] + public JoinDataComplete DirectoryLineSelected = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Line Selected FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryIsRoot")] + public JoinDataComplete DirectoryIsRoot = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory is on Root FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryHasChanged")] + public JoinDataComplete DirectoryHasChanged = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory has changed FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryRoot")] + public JoinDataComplete DirectoryRoot = new JoinDataComplete( + new JoinData + { + JoinNumber = 104, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Go to Directory Root", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryFolderBack")] + public JoinDataComplete DirectoryFolderBack = new JoinDataComplete( + new JoinData + { + JoinNumber = 105, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Go back one directory level", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDialSelectedLine")] + public JoinDataComplete DirectoryDialSelectedLine = new JoinDataComplete( + new JoinData + { + JoinNumber = 106, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Dial selected directory line", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("CameraTiltUp")] + public JoinDataComplete CameraTiltUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 111, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Tilt Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltDown")] + public JoinDataComplete CameraTiltDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 112, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Tilt Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanLeft")] + public JoinDataComplete CameraPanLeft = new JoinDataComplete( + new JoinData + { + JoinNumber = 113, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Pan Left", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanRight")] + public JoinDataComplete CameraPanRight = new JoinDataComplete( + new JoinData + { + JoinNumber = 114, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Pan Right", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomIn")] + public JoinDataComplete CameraZoomIn = new JoinDataComplete( + new JoinData + { + JoinNumber = 115, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Zoom In", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomOut")] + public JoinDataComplete CameraZoomOut = new JoinDataComplete( + new JoinData + { + JoinNumber = 116, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPresetSave")] + public JoinDataComplete CameraPresetSave = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Save Selected Preset", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeAuto")] + public JoinDataComplete CameraModeAuto = new JoinDataComplete( + new JoinData + { + JoinNumber = 131, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Auto", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeManual")] + public JoinDataComplete CameraModeManual = new JoinDataComplete( + new JoinData + { + JoinNumber = 132, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Manual", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeOff")] + public JoinDataComplete CameraModeOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 133, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Mode Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSelfView")] + public JoinDataComplete CameraSelfView = new JoinDataComplete( + new JoinData + { + JoinNumber = 141, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Self View Toggle/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraLayout")] + public JoinDataComplete CameraLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Layout Toggle", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsAutoMode")] + public JoinDataComplete CameraSupportsAutoMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 143, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Supports Auto Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsOffMode")] + public JoinDataComplete CameraSupportsOffMode = new JoinDataComplete( + new JoinData + { + JoinNumber = 144, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Supports Off Mode FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("UpdateMeetings")] + public JoinDataComplete UpdateMeetings = new JoinDataComplete( + new JoinData + { + JoinNumber = 160, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Update Meetings", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting1")] + public JoinDataComplete DialMeeting1 = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join first meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting2")] + public JoinDataComplete DialMeeting2 = new JoinDataComplete( + new JoinData + { + JoinNumber = 162, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join second meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialMeeting3")] + public JoinDataComplete DialMeeting3 = new JoinDataComplete( + new JoinData + { + JoinNumber = 163, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join third meeting", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOn")] + public JoinDataComplete MicMuteOn = new JoinDataComplete( + new JoinData + { + JoinNumber = 171, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteOff")] + public JoinDataComplete MicMuteOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 172, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MicMuteToggle")] + public JoinDataComplete MicMuteToggle = new JoinDataComplete( + new JoinData + { + JoinNumber = 173, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Mic Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeUp")] + public JoinDataComplete VolumeUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 174, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Up", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeDown")] + public JoinDataComplete VolumeDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 175, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Down", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOn")] + public JoinDataComplete VolumeMuteOn = new JoinDataComplete( + new JoinData + { + JoinNumber = 176, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute On", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteOff")] + public JoinDataComplete VolumeMuteOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 177, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("VolumeMuteToggle")] + public JoinDataComplete VolumeMuteToggle = new JoinDataComplete( + new JoinData + { + JoinNumber = 178, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Mute Toggle", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareStart")] + public JoinDataComplete SourceShareStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 201, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Start Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceShareEnd")] + public JoinDataComplete SourceShareEnd = new JoinDataComplete( + new JoinData + { + JoinNumber = 202, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Stop Sharing & Feedback", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("AutoShareWhileInCall")] + public JoinDataComplete SourceShareAutoStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 203, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "When high, will autostart sharing when a call is joined", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RecievingContent")] + public JoinDataComplete RecievingContent = new JoinDataComplete( + new JoinData + { + JoinNumber = 204, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Recieving content from the far end", + JoinType = eJoinType.Digital, + JoinCapabilities = eJoinCapabilities.ToSIMPL + }); + + [JoinName("SelfviewPosition")] + public JoinDataComplete SelfviewPosition = new JoinDataComplete( + new JoinData + { + JoinNumber = 211, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + #endregion + + + + #region Analog + + [JoinName("MinutesBeforeMeetingStart")] + public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 41, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Minutes before meeting start that a meeting is joinable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraNumberSelect")] + public JoinDataComplete CameraNumberSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 60, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Number Select/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectoryRowCount")] + public JoinDataComplete DirectoryRowCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Row Count FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectorySelectRow")] + public JoinDataComplete DirectorySelectRow = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Select Row", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CameraPresetSelect")] + public JoinDataComplete CameraPresetSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Preset Select", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ParticipantCount")] + public JoinDataComplete ParticipantCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 151, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Participant Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("Meeting Count Fb")] + public JoinDataComplete MeetingCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Meeting Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("VolumeLevel")] + public JoinDataComplete VolumeLevel = new JoinDataComplete( + new JoinData + { + JoinNumber = 174, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Volume Level", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + #endregion + + + + #region Serials + + [JoinName("CurrentDialString")] + public JoinDataComplete CurrentDialString = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Dial String", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("PhoneString")] - public JoinDataComplete PhoneDialString = - new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + public JoinDataComplete PhoneDialString = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, new JoinMetadata { Description = "Phone Dial String", @@ -2135,6 +2285,220 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Serial }); + [JoinName("CurrentCallName")] + public JoinDataComplete CurrentCallData = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Call Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CallDirection")] + public JoinDataComplete CallDirection = new JoinDataComplete( + new JoinData + { + JoinNumber = 22, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Call Direction", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallName")] + public JoinDataComplete IncomingCallName = new JoinDataComplete( + new JoinData + { + JoinNumber = 51, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallNumber")] + public JoinDataComplete IncomingCallNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 52, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Incoming Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("DirectorySearchString")] + public JoinDataComplete DirectorySearchString = new JoinDataComplete( + new JoinData + { + JoinNumber = 100, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Search String", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntries")] + public JoinDataComplete DirectoryEntries = new JoinDataComplete( + new JoinData + { + JoinNumber = 101, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Entries - XSig, 255 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("Schedule")] + public JoinDataComplete Schedule = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Schedule Data - XSIG", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraPresetNames")] + public JoinDataComplete CameraPresetNames = new JoinDataComplete( + new JoinData + { + JoinNumber = 121, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Preset Names - XSIG, max of 15", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraLayoutStringFb")] + public JoinDataComplete CameraLayoutStringFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 141, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Layout Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentParticipants")] + public JoinDataComplete CurrentParticipants = new JoinDataComplete( + new JoinData + { + JoinNumber = 151, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Current Participants XSig", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentSource")] + public JoinDataComplete CurrentSource = new JoinDataComplete( + new JoinData + { + JoinNumber = 201, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Current Source", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelfviewPositionFb")] + public JoinDataComplete SelfviewPositionFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 211, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "advance selfview position", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedName")] + public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( + new JoinData + { + JoinNumber = 356, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Entry Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedNumber")] + public JoinDataComplete DirectoryEntrySelectedNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 357, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Entry Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectorySelectedFolderName")] + public JoinDataComplete DirectorySelectedFolderName = new JoinDataComplete( + new JoinData + { + JoinNumber = 358, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Directory Folder Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion + + public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof(VideoCodecControllerJoinMap)) { 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 a693bb12..7fecc98a 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 @@ -559,10 +559,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec const int maxDigitals = 7; const int maxStrings = 1; const int maxAnalogs = 1; - const int offset = maxDigitals + maxStrings + maxAnalogs; - var digitalIndex = maxStrings + maxAnalogs * maxParticipants; //15 + const int offset = maxDigitals + maxStrings + maxAnalogs; // 9 + var digitalIndex = (maxStrings + maxAnalogs) * maxParticipants; // 100 var stringIndex = 0; - var analogIndex = 0; + var analogIndex = stringIndex + maxParticipants; var meetingIndex = 0; var tokenArray = new XSigToken[maxParticipants * offset]; From 4e041d17734bdd3756c77ef78facceb925a02c5e Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 11 May 2021 11:36:17 -0500 Subject: [PATCH 17/28] Removed unused DecodecParticipantsXSig method. --- .../VideoCodec/VideoCodecBase.cs | 41 ------------------- 1 file changed, 41 deletions(-) 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 7fecc98a..6f735740 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 @@ -618,47 +618,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec return GetXSigString(tokenArray); } - // TODO: #698 [ ] Figure out how to decode xsig data and trigger actions based on values from SIMPL - private void DecodeParticipantsXSig(string xsigData) - { - if (string.IsNullOrEmpty(xsigData)) return; - var bytes = Encoding.GetEncoding(XSigEncoding).GetBytes(xsigData); - using (var xsigStream = new XSigTokenStreamReader(new MemoryStream(bytes))) - { - XSigToken token = null; - while ((token = xsigStream.ReadXSigToken()) != null) - { - switch (token.TokenType) - { - case XSigTokenType.Digital: - { - var data = token as XSigDigitalToken; - if (data == null) return; - Debug.Console(1, this, "xSig Data TokenType: {0} | Index: {1} | Value: {2}", - data.TokenType, data.Index, data.Value.ToString()); - break; - } - case XSigTokenType.Analog: - { - var data = token as XSigAnalogToken; - if (data == null) return; - Debug.Console(1, this, "xSig Data TokenType: {0} | Index: {1} | Value: {2}", - data.TokenType, data.Index, data.Value); - break; - } - case XSigTokenType.Serial: - { - var data = token as XSigSerialToken; - if (data == null) return; - Debug.Console(1, this, "xSig Data TokenType: {0} | Index: {1} | Value: {2}", data.TokenType, data.Index, - data.Value); - break; - } - } - } - } - } - private void LinkVideoCodecContentSharingToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { SharingContentIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SourceShareStart.JoinNumber]); From b4edb021ee68f7a495f92ba7fc150a2947a41c96 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 11 May 2021 12:23:27 -0600 Subject: [PATCH 18/28] #698 merged in join map updates from JKD. Fixed enum bit comparison for available layout feedbacks --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 42 +++++----- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 8 +- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 78 +++++++++---------- 3 files changed, 61 insertions(+), 67 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 724331fb..c2d45e42 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -875,12 +875,11 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - // TODO: #698 Set Join number [JoinName("ParticipantAudioMuteToggleStart")] public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( new JoinData { - JoinNumber = 2001, + JoinNumber = 500, JoinSpan = 50 }, new JoinMetadata @@ -890,12 +889,11 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - // TODO: #698 Set Join number [JoinName("ParticipantVideoMuteToggleStart")] public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( new JoinData { - JoinNumber = 2101, + JoinNumber = 800, JoinSpan = 50 }, new JoinMetadata @@ -905,12 +903,11 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - // TODO: #698 Set Join number [JoinName("ParticipantPinToggleStart")] public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( new JoinData { - JoinNumber = 2201, + JoinNumber = 1100, JoinSpan = 50 }, new JoinMetadata @@ -2177,14 +2174,13 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - // TODO: #698 Set Join number [JoinName("ParticipantAudioMuteToggleStart")] public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 2001, - JoinSpan = 50 - }, + new JoinData + { + JoinNumber = 500, + JoinSpan = 50 + }, new JoinMetadata { Description = "Toggles the participant's audio mute status", @@ -2192,14 +2188,13 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - // TODO: #698 Set Join number [JoinName("ParticipantVideoMuteToggleStart")] public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 2101, - JoinSpan = 50 - }, + new JoinData + { + JoinNumber = 800, + JoinSpan = 50 + }, new JoinMetadata { Description = "Toggles the participant's video mute status", @@ -2207,14 +2202,13 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps JoinType = eJoinType.Digital }); - // TODO: #698 Set Join number [JoinName("ParticipantPinToggleStart")] public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 2201, - JoinSpan = 50 - }, + new JoinData + { + JoinNumber = 1100, + JoinSpan = 50 + }, new JoinMetadata { Description = "Toggles the participant's pin status", 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 10f5929d..5b5a2966 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 @@ -1727,13 +1727,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { layoutsCodec.AvailableLayoutsChanged += (o, a) => { - trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, a.AvailableLayouts + trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery)); - trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, a.AvailableLayouts + trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Speaker)); - trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, a.AvailableLayouts + trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip)); - trilist.SetBool(joinMap.LayoutShareAllIsAvailable.JoinNumber, a.AvailableLayouts + trilist.SetBool(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll == (a.AvailableLayouts & zConfiguration.eLayoutStyle.ShareAll)); }; 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 index 7ceb1ba3..61a59fff 100644 --- 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 @@ -164,47 +164,47 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom JoinType = eJoinType.Digital }); - [JoinName("ParticipantAudioMuteToggleStart")] - public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 500, - JoinSpan = 100 - }, - new JoinMetadata - { - Description = "Toggles the participant's audio mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + //[JoinName("ParticipantAudioMuteToggleStart")] + //public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( + // new JoinData + // { + // JoinNumber = 500, + // JoinSpan = 100 + // }, + // new JoinMetadata + // { + // Description = "Toggles the participant's audio mute status", + // JoinCapabilities = eJoinCapabilities.ToSIMPL, + // JoinType = eJoinType.Digital + // }); - [JoinName("ParticipantVideoMuteToggleStart")] - public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 800, - JoinSpan = 100 - }, - new JoinMetadata - { - Description = "Toggles the participant's video mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + //[JoinName("ParticipantVideoMuteToggleStart")] + //public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( + // new JoinData + // { + // JoinNumber = 800, + // JoinSpan = 100 + // }, + // new JoinMetadata + // { + // Description = "Toggles the participant's video mute status", + // JoinCapabilities = eJoinCapabilities.ToSIMPL, + // JoinType = eJoinType.Digital + // }); - [JoinName("ParticipantPinToggleStart")] - public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 1100, - JoinSpan = 100 - }, - new JoinMetadata - { - Description = "Toggles the participant's pin status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + //[JoinName("ParticipantPinToggleStart")] + //public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( + // new JoinData + // { + // JoinNumber = 1100, + // JoinSpan = 100 + // }, + // new JoinMetadata + // { + // Description = "Toggles the participant's pin status", + // JoinCapabilities = eJoinCapabilities.ToSIMPL, + // JoinType = eJoinType.Digital + // }); #endregion From 8d215930d9c2cb28796dc0872cc7e32681d83300 Mon Sep 17 00:00:00 2001 From: Jason T Alborough Date: Tue, 11 May 2021 15:20:35 -0400 Subject: [PATCH 19/28] Adds WriteControlProperty to ReconfigurableDevice CameraBase now uses ReconfigurableDevice --- .../Devices/ReconfigurableDevice.cs | 8 +++++++ .../Cameras/CameraBase.cs | 22 ++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs index 7b4f1c99..60c8db0c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs @@ -7,6 +7,8 @@ using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace PepperDash.Essentials.Core.Devices { @@ -52,6 +54,12 @@ namespace PepperDash.Essentials.Core.Devices Name = config.Name; } + protected virtual void WriteControlProperty(JToken controlObject) + { + Config.Properties["control"] = JToken.FromObject(controlObject); + CustomSetConfig(Config); + } + /// /// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc) /// diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs index 8b42cd82..edfd34cb 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs @@ -8,6 +8,8 @@ using Crestron.SimplSharp.Reflection; using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Devices; +using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Presets; using PepperDash.Essentials.Devices.Common.Codec; @@ -25,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras Focus = 8 } - public abstract class CameraBase : EssentialsDevice, IRoutingOutputs + public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs { public eCameraControlMode ControlMode { get; protected set; } @@ -70,12 +72,20 @@ namespace PepperDash.Essentials.Devices.Common.Cameras // A bitmasked value to indicate the movement capabilites of this camera protected eCameraCapabilities Capabilities { get; set; } - protected CameraBase(string key, string name) : - base(key, name) - { - OutputPorts = new RoutingPortCollection(); + protected CameraBase(DeviceConfig config) : base(config) + { + OutputPorts = new RoutingPortCollection(); - ControlMode = eCameraControlMode.Manual; + ControlMode = eCameraControlMode.Manual; + + } + + protected CameraBase(string key, string name) : + base (new DeviceConfig{Name = name, Key = key}) + { + OutputPorts = new RoutingPortCollection(); + + ControlMode = eCameraControlMode.Manual; } protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey, From da179c01f5098d1a5469bb84743f363f4cf1d2c0 Mon Sep 17 00:00:00 2001 From: Jason T Alborough Date: Tue, 11 May 2021 17:52:26 -0400 Subject: [PATCH 20/28] Fixes UpdateDeviceConfig() --- .../Config/Essentials/ConfigWriter.cs | 320 +++++++++--------- 1 file changed, 160 insertions(+), 160 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigWriter.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigWriter.cs index cb361d28..b97eeafa 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigWriter.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigWriter.cs @@ -1,162 +1,162 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronIO; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using PepperDash.Core; - -namespace PepperDash.Essentials.Core.Config -{ - /// - /// Responsible for updating config at runtime, and writing the updates out to a local file - /// - public class ConfigWriter - { - public const string LocalConfigFolder = "LocalConfig"; - - public const long WriteTimeout = 30000; - +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronIO; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.Config +{ + /// + /// Responsible for updating config at runtime, and writing the updates out to a local file + /// + public class ConfigWriter + { + public const string LocalConfigFolder = "LocalConfig"; + + public const long WriteTimeout = 30000; + public static CTimer WriteTimer; - static CCriticalSection fileLock = new CCriticalSection(); - - /// - /// Updates the config properties of a device - /// - /// - /// - /// - public static bool UpdateDeviceProperties(string deviceKey, JToken properties) - { - bool success = false; - - // Get the current device config - var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(deviceKey)); - - if (deviceConfig != null) - { - // Replace the current properties JToken with the new one passed into this method - deviceConfig.Properties = properties; - - Debug.Console(1, "Updated properties of device: '{0}'", deviceKey); - - success = true; - } - - ResetTimer(); - - return success; - } - - public static bool UpdateDeviceConfig(DeviceConfig config) - { - bool success = false; - - var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(config.Key)); - - if (deviceConfig != null) - { - deviceConfig = config; - - Debug.Console(1, "Updated config of device: '{0}'", config.Key); - - success = true; - } - - ResetTimer(); - - return success; - } - - public static bool UpdateRoomConfig(DeviceConfig config) - { - bool success = false; - - var deviceConfig = ConfigReader.ConfigObject.Rooms.FirstOrDefault(d => d.Key.Equals(config.Key)); - - if (deviceConfig != null) - { - deviceConfig = config; - - Debug.Console(1, "Updated config of device: '{0}'", config.Key); - - success = true; - } - - ResetTimer(); - - return success; - } - - /// - /// Resets (or starts) the write timer - /// - static void ResetTimer() - { - if (WriteTimer == null) - WriteTimer = new CTimer(WriteConfigFile, WriteTimeout); - - WriteTimer.Reset(WriteTimeout); - - Debug.Console(1, "Config File write timer has been reset."); - } - - /// - /// Writes the current config to a file in the LocalConfig subfolder - /// - /// - private static void WriteConfigFile(object o) - { - var filePath = Global.FilePathPrefix + LocalConfigFolder + Global.DirectorySeparator + "configurationFile.json"; - - var configData = JsonConvert.SerializeObject(ConfigReader.ConfigObject); - - WriteFile(filePath, configData); - } - - /// - /// Writes - /// - /// - /// - public static void WriteFile(string filePath, string configData) - { - if (WriteTimer != null) - WriteTimer.Stop(); - - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Writing Configuration to file"); - - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to write config file: '{0}'", filePath); - - try - { - if (fileLock.TryEnter()) - { - using (StreamWriter sw = new StreamWriter(filePath)) - { - sw.Write(configData); - sw.Flush(); - } - } - else - { - Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to enter FileLock"); - } - } - catch (Exception e) - { - Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: Config write failed: \r{0}", e); - } - finally - { - if (fileLock != null && !fileLock.Disposed) - fileLock.Leave(); - - } - } - - - } + static CCriticalSection fileLock = new CCriticalSection(); + + /// + /// Updates the config properties of a device + /// + /// + /// + /// + public static bool UpdateDeviceProperties(string deviceKey, JToken properties) + { + bool success = false; + + // Get the current device config + var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(deviceKey)); + + if (deviceConfig != null) + { + // Replace the current properties JToken with the new one passed into this method + deviceConfig.Properties = properties; + + Debug.Console(1, "Updated properties of device: '{0}'", deviceKey); + + success = true; + } + + ResetTimer(); + + return success; + } + + public static bool UpdateDeviceConfig(DeviceConfig config) + { + bool success = false; + + var deviceConfig = ConfigReader.ConfigObject.Devices.FindIndex(d => d.Key.Equals(config.Key)); + + if (deviceConfig >= 0) + { + ConfigReader.ConfigObject.Devices[deviceConfig] = config; + + Debug.Console(1, "Updated config of device: '{0}'", config.Key); + + success = true; + } + + ResetTimer(); + + return success; + } + + public static bool UpdateRoomConfig(DeviceConfig config) + { + bool success = false; + + var deviceConfig = ConfigReader.ConfigObject.Rooms.FirstOrDefault(d => d.Key.Equals(config.Key)); + + if (deviceConfig != null) + { + deviceConfig = config; + + Debug.Console(1, "Updated config of device: '{0}'", config.Key); + + success = true; + } + + ResetTimer(); + + return success; + } + + /// + /// Resets (or starts) the write timer + /// + static void ResetTimer() + { + if (WriteTimer == null) + WriteTimer = new CTimer(WriteConfigFile, WriteTimeout); + + WriteTimer.Reset(WriteTimeout); + + Debug.Console(1, "Config File write timer has been reset."); + } + + /// + /// Writes the current config to a file in the LocalConfig subfolder + /// + /// + private static void WriteConfigFile(object o) + { + var filePath = Global.FilePathPrefix + LocalConfigFolder + Global.DirectorySeparator + "configurationFile.json"; + + var configData = JsonConvert.SerializeObject(ConfigReader.ConfigObject); + + WriteFile(filePath, configData); + } + + /// + /// Writes + /// + /// + /// + public static void WriteFile(string filePath, string configData) + { + if (WriteTimer != null) + WriteTimer.Stop(); + + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Writing Configuration to file"); + + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to write config file: '{0}'", filePath); + + try + { + if (fileLock.TryEnter()) + { + using (StreamWriter sw = new StreamWriter(filePath)) + { + sw.Write(configData); + sw.Flush(); + } + } + else + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to enter FileLock"); + } + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: Config write failed: \r{0}", e); + } + finally + { + if (fileLock != null && !fileLock.Disposed) + fileLock.Leave(); + + } + } + + + } } \ No newline at end of file From c14193f9aca0c1fb019cf47346143b9d093f58f1 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 11 May 2021 18:13:18 -0500 Subject: [PATCH 21/28] Updates to VideoCodecControllerJoinMap to fix joins for Participant triggers. Updated ZoomRoomJoinMaps to implement zConfiguration.eLayoutStyle to pass the name across the bridge. --- .../JoinMaps/VideoCodecControllerJoinMap.cs | 8 +- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 4672 +++++++++-------- .../VideoCodec/ZoomRoom/ZoomRoomJoinMap.cs | 8 +- 3 files changed, 2348 insertions(+), 2340 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index c2d45e42..dcb66a2e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -879,7 +879,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( new JoinData { - JoinNumber = 500, + JoinNumber = 501, JoinSpan = 50 }, new JoinMetadata @@ -893,7 +893,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( new JoinData { - JoinNumber = 800, + JoinNumber = 801, JoinSpan = 50 }, new JoinMetadata @@ -907,7 +907,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( new JoinData { - JoinNumber = 1100, + JoinNumber = 1101, JoinSpan = 50 }, new JoinMetadata @@ -1237,7 +1237,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps Description = "advance selfview position", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial - }); + }); [JoinName("DirectoryEntrySelectedName")] public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( 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 5b5a2966..71882d5c 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 @@ -3,11 +3,13 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; +using Crestron.SimplSharp.Reflection; using Crestron.SimplSharpPro.CrestronThread; using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PepperDash.Core; +using PepperDash.Core.Intersystem.Tokens; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; @@ -20,1750 +22,1756 @@ using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { - public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, - IRouting, - IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, - IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasParticipantAudioMute - { - private const long MeetingRefreshTimer = 60000; - private const uint DefaultMeetingDurationMin = 30; - private const string Delimiter = "\x0D\x0A"; - private readonly CrestronQueue _receiveQueue; + public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, + IRouting, + IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, + IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasParticipantAudioMute + { + private const long MeetingRefreshTimer = 60000; + private const uint DefaultMeetingDurationMin = 30; + private const string Delimiter = "\x0D\x0A"; + private readonly CrestronQueue _receiveQueue; - private readonly Thread _receiveThread; + private readonly Thread _receiveThread; - private readonly ZoomRoomSyncState _syncState; - public bool CommDebuggingIsOn; - private CodecDirectory _currentDirectoryResult; - private uint _jsonCurlyBraceCounter; - private bool _jsonFeedbackMessageIsIncoming; - private StringBuilder _jsonMessage; - private int _previousVolumeLevel; - private CameraBase _selectedCamera; + private readonly ZoomRoomSyncState _syncState; + public bool CommDebuggingIsOn; + private CodecDirectory _currentDirectoryResult; + private uint _jsonCurlyBraceCounter; + private bool _jsonFeedbackMessageIsIncoming; + private StringBuilder _jsonMessage; + private int _previousVolumeLevel; + private CameraBase _selectedCamera; - private readonly ZoomRoomPropertiesConfig _props; + private readonly ZoomRoomPropertiesConfig _props; - public ZoomRoom(DeviceConfig config, IBasicCommunication comm) - : base(config) - { - _props = JsonConvert.DeserializeObject(config.Properties.ToString()); + public ZoomRoom(DeviceConfig config, IBasicCommunication comm) + : base(config) + { + _props = JsonConvert.DeserializeObject(config.Properties.ToString()); - // The queue that will collect the repsonses in the order they are received - _receiveQueue = new CrestronQueue(1024); + // 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}; + // The thread responsible for dequeuing and processing the messages + _receiveThread = new Thread(o => ProcessQueue(), null) { Priority = Thread.eThreadPriority.MediumPriority }; - Communication = comm; + Communication = comm; - if (_props.CommunicationMonitorProperties != null) - { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, - _props.CommunicationMonitorProperties); - } - else - { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, - "zStatus SystemUnit\r"); - } + if (_props.CommunicationMonitorProperties != null) + { + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, + _props.CommunicationMonitorProperties); + } + else + { + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, + "zStatus SystemUnit\r"); + } - DeviceManager.AddDevice(CommunicationMonitor); + DeviceManager.AddDevice(CommunicationMonitor); - Status = new ZoomRoomStatus(); + Status = new ZoomRoomStatus(); - Configuration = new ZoomRoomConfiguration(); + Configuration = new ZoomRoomConfiguration(); - CodecInfo = new ZoomRoomInfo(Status, Configuration); + CodecInfo = new ZoomRoomInfo(Status, Configuration); - _syncState = new ZoomRoomSyncState(Key + "--Sync", this); + _syncState = new ZoomRoomSyncState(Key + "--Sync", this); - _syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted; + _syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted; - PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); + PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); - PortGather = new CommunicationGather(Communication, "\x0A") {IncludeDelimiter = true}; - PortGather.LineReceived += Port_LineReceived; + PortGather = new CommunicationGather(Communication, "\x0A") { IncludeDelimiter = true }; + PortGather.LineReceived += Port_LineReceived; - CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, - eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this); + CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, + eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this); - Output1 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, - eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); + Output1 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, + eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null, this); - SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); + SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); - CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); + CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); - CameraIsMutedFeedback = CameraIsOffFeedback; + CameraIsMutedFeedback = CameraIsOffFeedback; - CameraAutoModeIsOnFeedback = new BoolFeedback(CameraAutoModeIsOnFeedbackFunc); + CameraAutoModeIsOnFeedback = new BoolFeedback(CameraAutoModeIsOnFeedbackFunc); - CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer); + CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer); - ReceivingContent = new BoolFeedback(FarEndIsSharingContentFeedbackFunc); + ReceivingContent = new BoolFeedback(FarEndIsSharingContentFeedbackFunc); - SelfviewPipPositionFeedback = new StringFeedback(SelfviewPipPositionFeedbackFunc); + SelfviewPipPositionFeedback = new StringFeedback(SelfviewPipPositionFeedbackFunc); - SetUpFeedbackActions(); + SetUpFeedbackActions(); - Cameras = new List(); + Cameras = new List(); - SetUpDirectory(); + SetUpDirectory(); - Participants = new CodecParticipants(); + Participants = new CodecParticipants(); - SupportsCameraOff = _props.SupportsCameraOff; - SupportsCameraAutoMode = _props.SupportsCameraAutoMode; + SupportsCameraOff = _props.SupportsCameraOff; + SupportsCameraAutoMode = _props.SupportsCameraAutoMode; - PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc); - CallerIdNameFeedback = new StringFeedback(CallerIdNameFeedbackFunc); - CallerIdNumberFeedback = new StringFeedback(CallerIdNumberFeedbackFunc); + PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc); + CallerIdNameFeedback = new StringFeedback(CallerIdNameFeedbackFunc); + CallerIdNumberFeedback = new StringFeedback(CallerIdNumberFeedbackFunc); - LocalLayoutFeedback = new StringFeedback(LocalLayoutFeedbackFunc); + LocalLayoutFeedback = new StringFeedback(LocalLayoutFeedbackFunc); - LayoutViewIsOnFirstPageFeedback = new BoolFeedback(LayoutViewIsOnFirstPageFeedbackFunc); - LayoutViewIsOnLastPageFeedback = new BoolFeedback(LayoutViewIsOnLastPageFeedbackFunc); - CanSwapContentWithThumbnailFeedback = new BoolFeedback(CanSwapContentWithThumbnailFeedbackFunc); - ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc); + LayoutViewIsOnFirstPageFeedback = new BoolFeedback(LayoutViewIsOnFirstPageFeedbackFunc); + LayoutViewIsOnLastPageFeedback = new BoolFeedback(LayoutViewIsOnLastPageFeedbackFunc); + CanSwapContentWithThumbnailFeedback = new BoolFeedback(CanSwapContentWithThumbnailFeedbackFunc); + ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc); - NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc); + NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc); - } + } - public CommunicationGather PortGather { get; private set; } + public CommunicationGather PortGather { get; private set; } - public ZoomRoomStatus Status { get; private set; } + public ZoomRoomStatus Status { get; private set; } - public ZoomRoomConfiguration Configuration { get; private set; } + public ZoomRoomConfiguration Configuration { get; private set; } - //CTimer LoginMessageReceivedTimer; - //CTimer RetryConnectionTimer; + //CTimer LoginMessageReceivedTimer; + //CTimer RetryConnectionTimer; - /// - /// Gets and returns the scaled volume of the codec - /// - protected override Func VolumeLevelFeedbackFunc - { - get - { - return () => CrestronEnvironment.ScaleWithLimits(Configuration.Audio.Output.Volume, 100, 0, 65535, 0); - } - } + /// + /// Gets and returns the scaled volume of the codec + /// + protected override Func VolumeLevelFeedbackFunc + { + get + { + return () => CrestronEnvironment.ScaleWithLimits(Configuration.Audio.Output.Volume, 100, 0, 65535, 0); + } + } - protected override Func PrivacyModeIsOnFeedbackFunc - { - get { return () => Configuration.Call.Microphone.Mute; } - } + protected override Func PrivacyModeIsOnFeedbackFunc + { + get { return () => Configuration.Call.Microphone.Mute; } + } - protected override Func StandbyIsOnFeedbackFunc - { - get { return () => false; } - } + protected override Func StandbyIsOnFeedbackFunc + { + get { return () => false; } + } - protected override Func SharingSourceFeedbackFunc - { - get { return () => Status.Sharing.dispState; } - } + protected override Func SharingSourceFeedbackFunc + { + get { return () => Status.Sharing.dispState; } + } - protected override Func SharingContentIsOnFeedbackFunc - { - get { return () => Status.Call.Sharing.IsSharing; } - } + protected override Func SharingContentIsOnFeedbackFunc + { + get { return () => Status.Call.Sharing.IsSharing; } + } - protected Func FarEndIsSharingContentFeedbackFunc - { - get { return () => Status.Call.Sharing.State == zEvent.eSharingState.Receiving; } - } + protected Func FarEndIsSharingContentFeedbackFunc + { + get { return () => Status.Call.Sharing.State == zEvent.eSharingState.Receiving; } + } - protected override Func MuteFeedbackFunc - { - get { return () => Configuration.Audio.Output.Volume == 0; } - } + protected override Func MuteFeedbackFunc + { + get { return () => Configuration.Audio.Output.Volume == 0; } + } - //protected Func RoomIsOccupiedFeedbackFunc - //{ - // get - // { - // return () => false; - // } - //} + //protected Func RoomIsOccupiedFeedbackFunc + //{ + // get + // { + // return () => false; + // } + //} - //protected Func PeopleCountFeedbackFunc - //{ - // get - // { - // return () => 0; - // } - //} + //protected Func PeopleCountFeedbackFunc + //{ + // get + // { + // return () => 0; + // } + //} - protected Func SelfViewIsOnFeedbackFunc - { - get { return () => !Configuration.Video.HideConfSelfVideo; } - } + protected Func SelfViewIsOnFeedbackFunc + { + get { return () => !Configuration.Video.HideConfSelfVideo; } + } - protected Func CameraIsOffFeedbackFunc - { - get { return () => Configuration.Call.Camera.Mute; } - } - - protected Func CameraAutoModeIsOnFeedbackFunc - { - get { return () => false; } - } - - protected Func SelfviewPipPositionFeedbackFunc - { - get - { - return - () => - _currentSelfviewPipPosition != null - ? _currentSelfviewPipPosition.Command ?? "Unknown" - : "Unknown"; - } - } - - protected Func LocalLayoutIsProminentFeedbackFunc - { - get { return () => false; } - } - - - public RoutingInputPort CodecOsdIn { get; private set; } - public RoutingOutputPort Output1 { get; private set; } - - #region ICommunicationMonitor Members - - public StatusMonitorBase CommunicationMonitor { get; private set; } - - #endregion - - #region IHasCodecCameras Members - - public event EventHandler CameraSelected; - - public List Cameras { get; private set; } - - public CameraBase SelectedCamera - { - get { return _selectedCamera; } - private set - { - _selectedCamera = value; - SelectedCameraFeedback.FireUpdate(); - ControllingFarEndCameraFeedback.FireUpdate(); - - var handler = CameraSelected; - if (handler != null) - { - handler(this, new CameraSelectedEventArgs(SelectedCamera)); - } - } - } - - - public StringFeedback SelectedCameraFeedback { get; private set; } - - public void SelectCamera(string key) - { - if (Cameras == null) - { - return; - } - - var camera = Cameras.FirstOrDefault(c => c.Key.IndexOf(key, StringComparison.OrdinalIgnoreCase) > -1); - if (camera != null) - { - Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); - SelectedCamera = camera; - } - else - { - Debug.Console(1, this, "Unable to select camera with key: '{0}'", key); - } - } + protected Func CameraIsOffFeedbackFunc + { + get { return () => Configuration.Call.Camera.Mute; } + } + + protected Func CameraAutoModeIsOnFeedbackFunc + { + get { return () => false; } + } + + protected Func SelfviewPipPositionFeedbackFunc + { + get + { + return + () => + _currentSelfviewPipPosition != null + ? _currentSelfviewPipPosition.Command ?? "Unknown" + : "Unknown"; + } + } + + protected Func LocalLayoutIsProminentFeedbackFunc + { + get { return () => false; } + } + + + public RoutingInputPort CodecOsdIn { get; private set; } + public RoutingOutputPort Output1 { get; private set; } + + #region ICommunicationMonitor Members + + public StatusMonitorBase CommunicationMonitor { get; private set; } + + #endregion + + #region IHasCodecCameras Members + + public event EventHandler CameraSelected; + + public List Cameras { get; private set; } + + public CameraBase SelectedCamera + { + get { return _selectedCamera; } + private set + { + _selectedCamera = value; + SelectedCameraFeedback.FireUpdate(); + ControllingFarEndCameraFeedback.FireUpdate(); + + var handler = CameraSelected; + if (handler != null) + { + handler(this, new CameraSelectedEventArgs(SelectedCamera)); + } + } + } + + + public StringFeedback SelectedCameraFeedback { get; private set; } + + public void SelectCamera(string key) + { + if (Cameras == null) + { + return; + } + + var camera = Cameras.FirstOrDefault(c => c.Key.IndexOf(key, StringComparison.OrdinalIgnoreCase) > -1); + if (camera != null) + { + Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); + SelectedCamera = camera; + } + else + { + Debug.Console(1, this, "Unable to select camera with key: '{0}'", key); + } + } - public CameraBase FarEndCamera { get; private set; } + public CameraBase FarEndCamera { get; private set; } - public BoolFeedback ControllingFarEndCameraFeedback { get; private set; } + public BoolFeedback ControllingFarEndCameraFeedback { get; private set; } - #endregion + #endregion - #region IHasCodecSelfView Members + #region IHasCodecSelfView Members - public BoolFeedback SelfviewIsOnFeedback { get; private set; } + public BoolFeedback SelfviewIsOnFeedback { get; private set; } - public void SelfViewModeOn() - { - SendText("zConfiguration Video hide_conf_self_video: off"); - } + public void SelfViewModeOn() + { + SendText("zConfiguration Video hide_conf_self_video: off"); + } - public void SelfViewModeOff() - { - SendText("zConfiguration Video hide_conf_self_video: on"); - } + public void SelfViewModeOff() + { + SendText("zConfiguration Video hide_conf_self_video: on"); + } - public void SelfViewModeToggle() - { - if (SelfviewIsOnFeedback.BoolValue) - { - SelfViewModeOff(); - } - else - { - SelfViewModeOn(); - } - } + public void SelfViewModeToggle() + { + if (SelfviewIsOnFeedback.BoolValue) + { + SelfViewModeOff(); + } + else + { + SelfViewModeOn(); + } + } - #endregion + #endregion - #region IHasDirectoryHistoryStack Members + #region IHasDirectoryHistoryStack Members - public event EventHandler DirectoryResultReturned; - public CodecDirectory DirectoryRoot { get; private set; } + public event EventHandler DirectoryResultReturned; + public CodecDirectory DirectoryRoot { get; private set; } - public CodecDirectory CurrentDirectoryResult - { - get { return _currentDirectoryResult; } - } + public CodecDirectory CurrentDirectoryResult + { + get { return _currentDirectoryResult; } + } - public CodecPhonebookSyncState PhonebookSyncState { get; private set; } + public CodecPhonebookSyncState PhonebookSyncState { get; private set; } - public void SearchDirectory(string searchString) - { - var directoryResults = new CodecDirectory(); + public void SearchDirectory(string searchString) + { + var directoryResults = new CodecDirectory(); - directoryResults.AddContactsToDirectory( - DirectoryRoot.CurrentDirectoryResults.FindAll( - c => c.Name.IndexOf(searchString, 0, StringComparison.OrdinalIgnoreCase) > -1)); + directoryResults.AddContactsToDirectory( + DirectoryRoot.CurrentDirectoryResults.FindAll( + c => c.Name.IndexOf(searchString, 0, StringComparison.OrdinalIgnoreCase) > -1)); - DirectoryBrowseHistoryStack.Clear(); - _currentDirectoryResult = directoryResults; + DirectoryBrowseHistoryStack.Clear(); + _currentDirectoryResult = directoryResults; - OnDirectoryResultReturned(directoryResults); - } + OnDirectoryResultReturned(directoryResults); + } - public void GetDirectoryFolderContents(string folderId) - { - var directoryResults = new CodecDirectory {ResultsFolderId = folderId}; + public void GetDirectoryFolderContents(string folderId) + { + var directoryResults = new CodecDirectory { ResultsFolderId = folderId }; - directoryResults.AddContactsToDirectory( - DirectoryRoot.CurrentDirectoryResults.FindAll(c => c.ParentFolderId.Equals(folderId))); + directoryResults.AddContactsToDirectory( + DirectoryRoot.CurrentDirectoryResults.FindAll(c => c.ParentFolderId.Equals(folderId))); - DirectoryBrowseHistoryStack.Push(_currentDirectoryResult); + DirectoryBrowseHistoryStack.Push(_currentDirectoryResult); - _currentDirectoryResult = directoryResults; + _currentDirectoryResult = directoryResults; - OnDirectoryResultReturned(directoryResults); - } + OnDirectoryResultReturned(directoryResults); + } - public void SetCurrentDirectoryToRoot() - { - DirectoryBrowseHistoryStack.Clear(); + public void SetCurrentDirectoryToRoot() + { + DirectoryBrowseHistoryStack.Clear(); - _currentDirectoryResult = DirectoryRoot; - - OnDirectoryResultReturned(DirectoryRoot); - } - - public void GetDirectoryParentFolderContents() - { - if (DirectoryBrowseHistoryStack.Count == 0) - { - return; - } - - var currentDirectory = DirectoryBrowseHistoryStack.Pop(); - - _currentDirectoryResult = currentDirectory; - - OnDirectoryResultReturned(currentDirectory); - } + _currentDirectoryResult = DirectoryRoot; + + OnDirectoryResultReturned(DirectoryRoot); + } + + public void GetDirectoryParentFolderContents() + { + if (DirectoryBrowseHistoryStack.Count == 0) + { + return; + } + + var currentDirectory = DirectoryBrowseHistoryStack.Pop(); + + _currentDirectoryResult = currentDirectory; + + OnDirectoryResultReturned(currentDirectory); + } - public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; } + public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; } - public List DirectoryBrowseHistory { get; private set; } + public List DirectoryBrowseHistory { get; private set; } - public Stack DirectoryBrowseHistoryStack { get; private set; } - - #endregion - - #region IHasScheduleAwareness Members - - public CodecScheduleAwareness CodecSchedule { get; private set; } - - public void GetSchedule() - { - GetBookings(); - } - - #endregion - - #region IRouting Members - - public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) - { - ExecuteSwitch(inputSelector); - } - - #endregion - - private void SyncState_InitialSyncCompleted(object sender, EventArgs e) - { - SetUpRouting(); - - SetIsReady(); - } - - private void SetUpCallFeedbackActions() - { - Status.Call.Sharing.PropertyChanged += (o, a) => - { - if (a.PropertyName == "State") - { - SharingContentIsOnFeedback.FireUpdate(); - ReceivingContent.FireUpdate(); - } - }; - - Status.Call.PropertyChanged += (o, a) => - { - if (a.PropertyName == "Info") - { - Debug.Console(1, this, "Updating Call Status"); - UpdateCallStatus(); - } - }; - } - - /// - /// Subscribes to the PropertyChanged events on the state objects and fires the corresponding feedbacks. - /// - private void SetUpFeedbackActions() - { - Configuration.Audio.Output.PropertyChanged += (o, a) => - { - if (a.PropertyName == "Volume") - { - VolumeLevelFeedback.FireUpdate(); - MuteFeedback.FireUpdate(); - } - }; - - Configuration.Call.Microphone.PropertyChanged += (o, a) => - { - if (a.PropertyName == "Mute") - { - PrivacyModeIsOnFeedback.FireUpdate(); - } - }; - - Configuration.Video.PropertyChanged += (o, a) => - { - if (a.PropertyName == "HideConfSelfVideo") - { - SelfviewIsOnFeedback.FireUpdate(); - } - }; - Configuration.Video.Camera.PropertyChanged += (o, a) => - { - if (a.PropertyName == "SelectedId") - { - SelectCamera(Configuration.Video.Camera.SelectedId); - // this will in turn fire the affected feedbacks - } - }; - - Configuration.Call.Camera.PropertyChanged += (o, a) => - { - Debug.Console(1, this, "Configuration.Call.Camera.PropertyChanged: {0}", a.PropertyName); - - if (a.PropertyName != "Mute") return; - - CameraIsOffFeedback.FireUpdate(); - CameraAutoModeIsOnFeedback.FireUpdate(); - }; - - Configuration.Call.Layout.PropertyChanged += (o, a) => - { - switch (a.PropertyName) - { - case "Position": - { - ComputeSelfviewPipStatus(); - - SelfviewPipPositionFeedback.FireUpdate(); - - break; - } - case "ShareThumb": - { - ContentSwappedWithThumbnailFeedback.FireUpdate(); - break; - } - case "Style": - { - LocalLayoutFeedback.FireUpdate(); - break; - } - - } - }; - - Status.Call.Sharing.PropertyChanged += (o, a) => - { - if (a.PropertyName == "State") - { - SharingContentIsOnFeedback.FireUpdate(); - ReceivingContent.FireUpdate(); - } - }; - - Status.Call.PropertyChanged += (o, a) => - { - if (a.PropertyName == "Info") - { - Debug.Console(1, this, "Updating Call Status"); - UpdateCallStatus(); - } - }; - - Status.Sharing.PropertyChanged += (o, a) => - { - switch (a.PropertyName) - { - case "dispState": - SharingSourceFeedback.FireUpdate(); - break; - case "password": - break; - } - }; - - Status.PhoneCall.PropertyChanged += (o, a) => - { - switch (a.PropertyName) - { - case "IsIncomingCall": - Debug.Console(1, this, "Incoming Phone Call: {0}", Status.PhoneCall.IsIncomingCall); - break; - case "PeerDisplayName": - Debug.Console(1, this, "Peer Display Name: {0}", Status.PhoneCall.PeerDisplayName); - CallerIdNameFeedback.FireUpdate(); - break; - case "PeerNumber": - Debug.Console(1, this, "Peer Number: {0}", Status.PhoneCall.PeerNumber); - CallerIdNumberFeedback.FireUpdate(); - break; - case "OffHook": - Debug.Console(1, this, "Phone is OffHook: {0}", Status.PhoneCall.OffHook); - PhoneOffHookFeedback.FireUpdate(); - break; - } - }; - - Status.Layout.PropertyChanged += (o, a) => - { - switch (a.PropertyName) - { - case "can_Switch_Speaker_View": - case "can_Switch_Wall_View": - case "can_Switch_Share_On_All_Screens": - { - ComputeAvailableLayouts(); - break; - } - case "is_In_First_Page": - { - LayoutViewIsOnFirstPageFeedback.FireUpdate(); - break; - } - case "is_In_Last_Page": - { - LayoutViewIsOnLastPageFeedback.FireUpdate(); - break; - } - //case "video_type": - // { - // It appears as though the actual value we want to watch is Configuration.Call.Layout.Style - // LocalLayoutFeedback.FireUpdate(); - // break; - // } - } - }; - - Status.NumberOfScreens.PropertyChanged += (o, a) => - { - switch (a.PropertyName) - { - case "NumberOfScreens": - { - NumberOfScreensFeedback.FireUpdate(); - break; - } - } - }; - } - - private void SetUpDirectory() - { - DirectoryRoot = new CodecDirectory(); - - DirectoryBrowseHistory = new List(); - DirectoryBrowseHistoryStack = new Stack(); - - CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => _currentDirectoryResult != DirectoryRoot); - - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); - } - - private void SetUpRouting() - { - // Set up input ports - CreateOsdSource(); - InputPorts.Add(CodecOsdIn); - - // Set up output ports - OutputPorts.Add(Output1); - } - - /// - /// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input - /// to enable routing - /// - private void CreateOsdSource() - { - OsdSource = new DummyRoutingInputsDevice(Key + "[osd]"); - DeviceManager.AddDevice(OsdSource); - var tl = new TieLine(OsdSource.AudioVideoOutputPort, CodecOsdIn); - TieLineCollection.Default.Add(tl); - - //foreach(var input in Status.Video. - } - - /// - /// Starts the HTTP feedback server and syncronizes state of codec - /// - /// - public override bool CustomActivate() - { - CrestronConsole.AddNewConsoleCommand(SetCommDebug, "SetCodecCommDebug", "0 for Off, 1 for on", - ConsoleAccessLevelEnum.AccessOperator); - if (!_props.DisablePhonebookAutoDownload) - { - CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), - "GetZoomRoomContacts", "Triggers a refresh of the codec phonebook", - ConsoleAccessLevelEnum.AccessOperator); - } - - CrestronConsole.AddNewConsoleCommand(s => GetBookings(), "GetZoomRoomBookings", - "Triggers a refresh of the booking data for today", ConsoleAccessLevelEnum.AccessOperator); - - var socket = Communication as ISocketStatus; - if (socket != null) - { - socket.ConnectionChange += socket_ConnectionChange; - } - - CommDebuggingIsOn = false; - - Communication.Connect(); - - CommunicationMonitor.Start(); - - return base.CustomActivate(); - } - - public void SetCommDebug(string s) - { - if (s == "1") - { - CommDebuggingIsOn = true; - Debug.Console(0, this, "Comm Debug Enabled."); - } - else - { - CommDebuggingIsOn = false; - Debug.Console(0, this, "Comm Debug Disabled."); - } - } - - private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) - { - Debug.Console(1, this, "Socket status change {0}", e.Client.ClientStatus); - if (e.Client.IsConnected) - { - } - else - { - _syncState.CodecDisconnected(); - PhonebookSyncState.CodecDisconnected(); - } - } - - public void SendText(string command) - { - if (CommDebuggingIsOn) - { - Debug.Console(1, this, "Sending: '{0}'", command); - } - - Communication.SendText(command + Delimiter); - } - - /// - /// Gathers responses and enqueues them. - /// - /// - /// - private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) - { - //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; - } - - - /// - /// Queues the initial queries to be sent upon connection - /// - private void SetUpSyncQueries() - { - // zStatus - _syncState.AddQueryToQueue("zStatus Call Status"); - _syncState.AddQueryToQueue("zStatus Audio Input Line"); - _syncState.AddQueryToQueue("zStatus Audio Output Line"); - _syncState.AddQueryToQueue("zStatus Video Camera Line"); - _syncState.AddQueryToQueue("zStatus Video Optimizable"); - _syncState.AddQueryToQueue("zStatus Capabilities"); - _syncState.AddQueryToQueue("zStatus Sharing"); - _syncState.AddQueryToQueue("zStatus CameraShare"); - _syncState.AddQueryToQueue("zStatus Call Layout"); - _syncState.AddQueryToQueue("zStatus Call ClosedCaption Available"); - _syncState.AddQueryToQueue("zStatus NumberOfScreens"); - - // zConfiguration - - _syncState.AddQueryToQueue("zConfiguration Call Sharing optimize_video_sharing"); - _syncState.AddQueryToQueue("zConfiguration Call Microphone Mute"); - _syncState.AddQueryToQueue("zConfiguration Call Camera Mute"); - _syncState.AddQueryToQueue("zConfiguration Audio Input SelectedId"); - _syncState.AddQueryToQueue("zConfiguration Audio Input is_sap_disabled"); - _syncState.AddQueryToQueue("zConfiguration Audio Input reduce_reverb"); - _syncState.AddQueryToQueue("zConfiguration Audio Input volume"); - _syncState.AddQueryToQueue("zConfiguration Audio Output selectedId"); - _syncState.AddQueryToQueue("zConfiguration Audio Output volume"); - _syncState.AddQueryToQueue("zConfiguration Video hide_conf_self_video"); - _syncState.AddQueryToQueue("zConfiguration Video Camera selectedId"); - _syncState.AddQueryToQueue("zConfiguration Video Camera Mirror"); - _syncState.AddQueryToQueue("zConfiguration Client appVersion"); - _syncState.AddQueryToQueue("zConfiguration Client deviceSystem"); - _syncState.AddQueryToQueue("zConfiguration Call Layout ShareThumb"); - _syncState.AddQueryToQueue("zConfiguration Call Layout Style"); - _syncState.AddQueryToQueue("zConfiguration Call Layout Size"); - _syncState.AddQueryToQueue("zConfiguration Call Layout Position"); - _syncState.AddQueryToQueue("zConfiguration Call Lock Enable"); - _syncState.AddQueryToQueue("zConfiguration Call MuteUserOnEntry Enable"); - _syncState.AddQueryToQueue("zConfiguration Call ClosedCaption FontSize "); - _syncState.AddQueryToQueue("zConfiguration Call ClosedCaption Visible"); - - // zCommand - - if (!_props.DisablePhonebookAutoDownload) - { - _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 512"); - } - - _syncState.AddQueryToQueue("zCommand Bookings List"); - _syncState.AddQueryToQueue("zCommand Call ListParticipants"); - _syncState.AddQueryToQueue("zCommand Call Info"); - - - _syncState.StartSync(); - } - - /// - /// Processes messages as they are dequeued - /// - /// - private void ProcessMessage(string message) - { - // Counts the curly braces - if (message.Contains("client_loop: send disconnect: Broken pipe")) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Error, - "Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected."); - - return; - } - - if (message.Contains('{')) - { - _jsonCurlyBraceCounter++; - } - - if (message.Contains('}')) - { - _jsonCurlyBraceCounter--; - } - - Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); - - if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) - // Check for the beginning of a new JSON message - { - _jsonFeedbackMessageIsIncoming = true; - _jsonCurlyBraceCounter = 1; // reset the counter for each new message - - _jsonMessage = new StringBuilder(); - - _jsonMessage.Append(message); - - if (CommDebuggingIsOn) - { - Debug.Console(2, this, "Incoming JSON message..."); - } - - return; - } - if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) - // Check for the end of a JSON message - { - _jsonMessage.Append(message); - - if (_jsonCurlyBraceCounter == 0) - { - _jsonFeedbackMessageIsIncoming = false; - - if (CommDebuggingIsOn) - { - Debug.Console(2, this, "Complete JSON Received:\n{0}", _jsonMessage.ToString()); - } - - // Forward the complete message to be deserialized - DeserializeResponse(_jsonMessage.ToString()); - } - - //JsonMessage = new StringBuilder(); - return; - } - - // NOTE: This must happen after the above conditions have been checked - // Append subsequent partial JSON fragments to the string builder - if (_jsonFeedbackMessageIsIncoming) - { - _jsonMessage.Append(message); - - //Debug.Console(1, this, "Building JSON:\n{0}", JsonMessage.ToString()); - return; - } - - if (CommDebuggingIsOn) - { - Debug.Console(1, this, "Non-JSON response: '{0}'", message); - } - - _jsonCurlyBraceCounter = 0; // reset on non-JSON response - - if (!_syncState.InitialSyncComplete) - { - switch (message.Trim().ToLower()) // remove the whitespace - { - case "*r login successful": - { - _syncState.LoginMessageReceived(); - - // Fire up a thread to send the intial commands. - CrestronInvoke.BeginInvoke(o => - { - Thread.Sleep(100); - // disable echo of commands - SendText("echo off"); - Thread.Sleep(100); - // set feedback exclusions - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/info/callin_country_list"); - Thread.Sleep(100); - SendText("zFeedback Register Op: ex Path: /Event/InfoResult/info/callout_country_list"); - Thread.Sleep(100); - - if (!_props.DisablePhonebookAutoDownload) - { - SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); - } - // switch to json format - SendText("format json"); - }); - - break; - } - } - } - } - - /// - /// Deserializes a JSON formatted response - /// - /// - private void DeserializeResponse(string response) - { - try - { - var trimmedResponse = response.Trim(); - - if (trimmedResponse.Length <= 0) - { - return; - } - - var message = JObject.Parse(trimmedResponse); - - var eType = - (eZoomRoomResponseType) - Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value(), true); - - var topKey = message["topKey"].Value(); - - var responseObj = message[topKey]; - - Debug.Console(1, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString()); - - switch (eType) - { - case eZoomRoomResponseType.zConfiguration: - { - switch (topKey.ToLower()) - { - case "call": - { - JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Call); - - break; - } - case "audio": - { - JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Audio); - - break; - } - case "video": - { - JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Video); - - break; - } - case "client": - { - JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Client); - - break; - } - default: - { - break; - } - } - break; - } - case eZoomRoomResponseType.zCommand: - { - switch (topKey.ToLower()) - { - case "inforesult": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Info); - break; - } - case "phonebooklistresult": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); - - if (!PhonebookSyncState.InitialSyncComplete) - { - PhonebookSyncState.InitialPhonebookFoldersReceived(); - PhonebookSyncState.PhonebookRootEntriesReceived(); - PhonebookSyncState.SetPhonebookHasFolders(false); - PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); - } - - var directoryResults = - zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); - - DirectoryRoot = directoryResults; - - _currentDirectoryResult = DirectoryRoot; - - OnDirectoryResultReturned(directoryResults); - - break; - } - case "listparticipantsresult": - { - Debug.Console(1, this, "JTokenType: {0}", responseObj.Type); - - switch (responseObj.Type) - { - case JTokenType.Array: - Status.Call.Participants = - JsonConvert.DeserializeObject>( - responseObj.ToString()); - break; - case JTokenType.Object: - { - // this is a single participant event notification - - var participant = - JsonConvert.DeserializeObject( - responseObj.ToString()); - - if (participant != null) - { - switch (participant.Event) - { - case "ZRCUserChangedEventUserInfoUpdated": - case "ZRCUserChangedEventLeftMeeting": - { - var existingParticipant = - Status.Call.Participants.FirstOrDefault( - p => p.UserId.Equals(participant.UserId)); - - if (existingParticipant != null) - { - switch (participant.Event) - { - case "ZRCUserChangedEventLeftMeeting": - Status.Call.Participants.Remove(existingParticipant); - break; - case "ZRCUserChangedEventUserInfoUpdated": - JsonConvert.PopulateObject(responseObj.ToString(), - existingParticipant); - break; - } - } - } - break; - case "ZRCUserChangedEventJoinedMeeting": - Status.Call.Participants.Add(participant); - break; - } - } - } - break; - } - - var participants = - zCommand.ListParticipant.GetGenericParticipantListFromParticipantsResult( - Status.Call.Participants); - - Participants.CurrentParticipants = participants; - - PrintCurrentCallParticipants(); - - break; - } - default: - { - break; - } - } - break; - } - case eZoomRoomResponseType.zEvent: - { - switch (topKey.ToLower()) - { - case "phonebook": - { - if (responseObj["Updated Contact"] != null) - { - var updatedContact = - JsonConvert.DeserializeObject( - responseObj["Updated Contact"].ToString()); - - var existingContact = - Status.Phonebook.Contacts.FirstOrDefault(c => c.Jid.Equals(updatedContact.Jid)); - - if (existingContact != null) - { - // Update existing contact - JsonConvert.PopulateObject(responseObj["Updated Contact"].ToString(), - existingContact); - } - } - else if (responseObj["Added Contact"] != null) - { - var jToken = responseObj["Updated Contact"]; - if (jToken != null) - { - var newContact = - JsonConvert.DeserializeObject( - jToken.ToString()); - - // Add a new contact - Status.Phonebook.Contacts.Add(newContact); - } - } - - break; - } - case "bookingslistresult": - { - if (!_syncState.InitialSyncComplete) - { - _syncState.LastQueryResponseReceived(); - } - - var codecBookings = JsonConvert.DeserializeObject>( - responseObj.ToString()); - - if (codecBookings != null && codecBookings.Count > 0) - { - CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult( - codecBookings, CodecSchedule.MeetingWarningMinutes); - } - - break; - } - case "bookings updated": - { - GetBookings(); - - break; - } - case "sharingstate": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); - - SetLayout(); - - break; - } - case "incomingcallindication": - { - var incomingCall = - JsonConvert.DeserializeObject(responseObj.ToString()); - - if (incomingCall != null) - { - var newCall = new CodecActiveCallItem - { - Direction = eCodecCallDirection.Incoming, - Status = eCodecCallStatus.Ringing, - Type = eCodecCallType.Unknown, - Name = incomingCall.callerName, - Id = incomingCall.callerJID - }; - - ActiveCalls.Add(newCall); - - OnCallStatusChange(newCall); - } - - break; - } - case "treatedincomingcallindication": - { - var incomingCall = - JsonConvert.DeserializeObject(responseObj.ToString()); - - if (incomingCall != null) - { - var existingCall = - ActiveCalls.FirstOrDefault(c => c.Id.Equals(incomingCall.callerJID)); - - if (existingCall != null) - { - existingCall.Status = !incomingCall.accepted - ? eCodecCallStatus.Disconnected - : eCodecCallStatus.Connecting; - - OnCallStatusChange(existingCall); - } - - UpdateCallStatus(); - } - - break; - } - case "calldisconnect": - { - var disconnectEvent = - JsonConvert.DeserializeObject(responseObj.ToString()); - - if (disconnectEvent.Successful) - { - if (ActiveCalls.Count > 0) - { - var activeCall = ActiveCalls.FirstOrDefault(c => c.IsActiveCall); - - if (activeCall != null) - { - activeCall.Status = eCodecCallStatus.Disconnected; - - OnCallStatusChange(activeCall); - } - } - var emptyList = new List(); - Participants.CurrentParticipants = emptyList; - } - - UpdateCallStatus(); - break; - } - case "callconnecterror": - { - UpdateCallStatus(); - break; - } - case "videounmuterequest": - { - // TODO: notify room of a request to unmute video - break; - } - case "meetingneedspassword": - { - // TODO: notify user to enter a password - break; - } - case "needwaitforhost": - { - var needWait = - JsonConvert.DeserializeObject(responseObj.ToString()); - - if (needWait.Wait) - { - // TODO: notify user to wait for host - } - - break; - } - case "openvideofailforhoststop": - { - // TODO: notify user that host has disabled unmuting video - break; - } - case "updatedcallrecordinfo": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo); - - break; - } - case "phonecallstatus": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); - break; - } - case "pinstatusofscreennotification": - { - var status = responseObj.ToObject(); - - var participant = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(status.PinnedUserId)); - - if (participant != null) - { - participant.IsPinnedFb = true; - participant.ScreenIndexIsPinnedToFb = status.ScreenIndex; - } - else - { - participant = Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); - - if (participant == null) - { - Debug.Console(2, this, "no matching participant found by pinned_user_id: {0} or screen_index: {1}", status.PinnedUserId, status.ScreenIndex); - return; - } - else - { - participant.IsPinnedFb = false; - participant.ScreenIndexIsPinnedToFb = -1; - } - } - - // fire the event as we've modified the participants list - Participants.OnParticipantsChanged(); - - break; - } - default: - { - break; - } - } - break; - } - case eZoomRoomResponseType.zStatus: - { - switch (topKey.ToLower()) - { - case "login": - { - _syncState.LoginMessageReceived(); - - if (!_syncState.InitialQueryMessagesWereSent) - { - SetUpSyncQueries(); - } - - JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); - - break; - } - case "systemunit": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); - - break; - } - case "call": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Call); - - UpdateCallStatus(); - - break; - } - case "capabilities": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Capabilities); - break; - } - case "sharing": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Sharing); - - break; - } - case "numberofscreens": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.NumberOfScreens); - break; - } - case "video": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Video); - break; - } - case "camerashare": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.CameraShare); - break; - } - case "layout": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Layout); - break; - } - case "audio input line": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioInputs); - break; - } - case "audio output line": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioOuputs); - break; - } - case "video camera line": - { - JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); - - if (!_syncState.CamerasHaveBeenSetUp) - { - SetUpCameras(); - } - - break; - } - default: - { - break; - } - } - - break; - } - default: - { - Debug.Console(1, "Unknown Response Type:"); - break; - } - } - } - catch (Exception ex) - { - Debug.Console(1, this, "Error Deserializing feedback: {0}", ex); - } - } - - private void SetLayout() - { - if (!_props.AutoDefaultLayouts) return; - - if ( - (Status.Call.Sharing.State == zEvent.eSharingState.Receiving || - Status.Call.Sharing.State == zEvent.eSharingState.Sending)) - { - SendText(String.Format("zconfiguration call layout style: {0}", - _props.DefaultSharingLayout)); - } - else - { - SendText(String.Format("zconfiguration call layout style: {0}", - _props.DefaultCallLayout)); - } - } - - public void PrintCurrentCallParticipants() - { - if (Debug.Level <= 0) - { - return; - } - - Debug.Console(1, this, "****************************Call Participants***************************"); - foreach (var participant in Participants.CurrentParticipants) - { - Debug.Console(1, this, "Name: {0} Audio: {1} IsHost: {2}", participant.Name, - participant.AudioMuteFb, participant.IsHost); - } - Debug.Console(1, this, "************************************************************************"); - } - - /// - /// Retrieves bookings list - /// - private void GetBookings() - { - SendText("zCommand Bookings List"); - } - - - /// - /// Updates the current call status - /// - private void UpdateCallStatus() - { - Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", - Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); - - if (Status.Call != null) - { - var callStatus = Status.Call.Status; - - // If not currently in a meeting, intialize the call object - if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING) - { - Debug.Console(1, this, "Creating new Status.Call object"); - Status.Call = new zStatus.Call {Status = callStatus}; - - SetUpCallFeedbackActions(); - } - - if (ActiveCalls.Count == 0) - { - if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING || - callStatus == zStatus.eCallStatus.IN_MEETING) - { - var newStatus = eCodecCallStatus.Unknown; - - switch (callStatus) - { - case zStatus.eCallStatus.CONNECTING_MEETING: - newStatus = eCodecCallStatus.Connecting; - break; - case zStatus.eCallStatus.IN_MEETING: - newStatus = eCodecCallStatus.Connected; - break; - } - - var newCall = new CodecActiveCallItem {Status = newStatus}; - - ActiveCalls.Add(newCall); - - Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", - Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); - - OnCallStatusChange(newCall); - } - } - else - { - var existingCall = ActiveCalls.FirstOrDefault(c => !c.Status.Equals(eCodecCallStatus.Ringing)); - - switch (callStatus) - { - case zStatus.eCallStatus.IN_MEETING: - existingCall.Status = eCodecCallStatus.Connected; - break; - case zStatus.eCallStatus.NOT_IN_MEETING: - existingCall.Status = eCodecCallStatus.Disconnected; - break; - } - - Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", - Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); - - OnCallStatusChange(existingCall); - } - } - - Debug.Console(1, this, "****************************Active Calls*********************************"); - - // Clean up any disconnected calls left in the list - for (int i = 0; i < ActiveCalls.Count; i++) - { - var call = ActiveCalls[i]; - - Debug.Console(1, this, - @"Name: {0} + public Stack DirectoryBrowseHistoryStack { get; private set; } + + #endregion + + #region IHasScheduleAwareness Members + + public CodecScheduleAwareness CodecSchedule { get; private set; } + + public void GetSchedule() + { + GetBookings(); + } + + #endregion + + #region IRouting Members + + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) + { + ExecuteSwitch(inputSelector); + } + + #endregion + + private void SyncState_InitialSyncCompleted(object sender, EventArgs e) + { + SetUpRouting(); + + SetIsReady(); + } + + private void SetUpCallFeedbackActions() + { + Status.Call.Sharing.PropertyChanged += (o, a) => + { + if (a.PropertyName == "State") + { + SharingContentIsOnFeedback.FireUpdate(); + ReceivingContent.FireUpdate(); + } + }; + + Status.Call.PropertyChanged += (o, a) => + { + if (a.PropertyName == "Info") + { + Debug.Console(1, this, "Updating Call Status"); + UpdateCallStatus(); + } + }; + } + + /// + /// Subscribes to the PropertyChanged events on the state objects and fires the corresponding feedbacks. + /// + private void SetUpFeedbackActions() + { + Configuration.Audio.Output.PropertyChanged += (o, a) => + { + if (a.PropertyName == "Volume") + { + VolumeLevelFeedback.FireUpdate(); + MuteFeedback.FireUpdate(); + } + }; + + Configuration.Call.Microphone.PropertyChanged += (o, a) => + { + if (a.PropertyName == "Mute") + { + PrivacyModeIsOnFeedback.FireUpdate(); + } + }; + + Configuration.Video.PropertyChanged += (o, a) => + { + if (a.PropertyName == "HideConfSelfVideo") + { + SelfviewIsOnFeedback.FireUpdate(); + } + }; + Configuration.Video.Camera.PropertyChanged += (o, a) => + { + if (a.PropertyName == "SelectedId") + { + SelectCamera(Configuration.Video.Camera.SelectedId); + // this will in turn fire the affected feedbacks + } + }; + + Configuration.Call.Camera.PropertyChanged += (o, a) => + { + Debug.Console(1, this, "Configuration.Call.Camera.PropertyChanged: {0}", a.PropertyName); + + if (a.PropertyName != "Mute") return; + + CameraIsOffFeedback.FireUpdate(); + CameraAutoModeIsOnFeedback.FireUpdate(); + }; + + Configuration.Call.Layout.PropertyChanged += (o, a) => + { + switch (a.PropertyName) + { + case "Position": + { + ComputeSelfviewPipStatus(); + + SelfviewPipPositionFeedback.FireUpdate(); + + break; + } + case "ShareThumb": + { + ContentSwappedWithThumbnailFeedback.FireUpdate(); + break; + } + case "Style": + { + LocalLayoutFeedback.FireUpdate(); + break; + } + + } + }; + + Status.Call.Sharing.PropertyChanged += (o, a) => + { + if (a.PropertyName == "State") + { + SharingContentIsOnFeedback.FireUpdate(); + ReceivingContent.FireUpdate(); + } + }; + + Status.Call.PropertyChanged += (o, a) => + { + if (a.PropertyName == "Info") + { + Debug.Console(1, this, "Updating Call Status"); + UpdateCallStatus(); + } + }; + + Status.Sharing.PropertyChanged += (o, a) => + { + switch (a.PropertyName) + { + case "dispState": + SharingSourceFeedback.FireUpdate(); + break; + case "password": + break; + } + }; + + Status.PhoneCall.PropertyChanged += (o, a) => + { + switch (a.PropertyName) + { + case "IsIncomingCall": + Debug.Console(1, this, "Incoming Phone Call: {0}", Status.PhoneCall.IsIncomingCall); + break; + case "PeerDisplayName": + Debug.Console(1, this, "Peer Display Name: {0}", Status.PhoneCall.PeerDisplayName); + CallerIdNameFeedback.FireUpdate(); + break; + case "PeerNumber": + Debug.Console(1, this, "Peer Number: {0}", Status.PhoneCall.PeerNumber); + CallerIdNumberFeedback.FireUpdate(); + break; + case "OffHook": + Debug.Console(1, this, "Phone is OffHook: {0}", Status.PhoneCall.OffHook); + PhoneOffHookFeedback.FireUpdate(); + break; + } + }; + + Status.Layout.PropertyChanged += (o, a) => + { + switch (a.PropertyName) + { + case "can_Switch_Speaker_View": + case "can_Switch_Wall_View": + case "can_Switch_Share_On_All_Screens": + { + ComputeAvailableLayouts(); + break; + } + case "is_In_First_Page": + { + LayoutViewIsOnFirstPageFeedback.FireUpdate(); + break; + } + case "is_In_Last_Page": + { + LayoutViewIsOnLastPageFeedback.FireUpdate(); + break; + } + //case "video_type": + // { + // It appears as though the actual value we want to watch is Configuration.Call.Layout.Style + // LocalLayoutFeedback.FireUpdate(); + // break; + // } + } + }; + + Status.NumberOfScreens.PropertyChanged += (o, a) => + { + switch (a.PropertyName) + { + case "NumberOfScreens": + { + NumberOfScreensFeedback.FireUpdate(); + break; + } + } + }; + } + + private void SetUpDirectory() + { + DirectoryRoot = new CodecDirectory(); + + DirectoryBrowseHistory = new List(); + DirectoryBrowseHistoryStack = new Stack(); + + CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => _currentDirectoryResult != DirectoryRoot); + + CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + } + + private void SetUpRouting() + { + // Set up input ports + CreateOsdSource(); + InputPorts.Add(CodecOsdIn); + + // Set up output ports + OutputPorts.Add(Output1); + } + + /// + /// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input + /// to enable routing + /// + private void CreateOsdSource() + { + OsdSource = new DummyRoutingInputsDevice(Key + "[osd]"); + DeviceManager.AddDevice(OsdSource); + var tl = new TieLine(OsdSource.AudioVideoOutputPort, CodecOsdIn); + TieLineCollection.Default.Add(tl); + + //foreach(var input in Status.Video. + } + + /// + /// Starts the HTTP feedback server and syncronizes state of codec + /// + /// + public override bool CustomActivate() + { + CrestronConsole.AddNewConsoleCommand(SetCommDebug, "SetCodecCommDebug", "0 for Off, 1 for on", + ConsoleAccessLevelEnum.AccessOperator); + if (!_props.DisablePhonebookAutoDownload) + { + CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), + "GetZoomRoomContacts", "Triggers a refresh of the codec phonebook", + ConsoleAccessLevelEnum.AccessOperator); + } + + CrestronConsole.AddNewConsoleCommand(s => GetBookings(), "GetZoomRoomBookings", + "Triggers a refresh of the booking data for today", ConsoleAccessLevelEnum.AccessOperator); + + var socket = Communication as ISocketStatus; + if (socket != null) + { + socket.ConnectionChange += socket_ConnectionChange; + } + + CommDebuggingIsOn = false; + + Communication.Connect(); + + CommunicationMonitor.Start(); + + return base.CustomActivate(); + } + + public void SetCommDebug(string s) + { + if (s == "1") + { + CommDebuggingIsOn = true; + Debug.Console(0, this, "Comm Debug Enabled."); + } + else + { + CommDebuggingIsOn = false; + Debug.Console(0, this, "Comm Debug Disabled."); + } + } + + private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) + { + Debug.Console(1, this, "Socket status change {0}", e.Client.ClientStatus); + if (e.Client.IsConnected) + { + } + else + { + _syncState.CodecDisconnected(); + PhonebookSyncState.CodecDisconnected(); + } + } + + public void SendText(string command) + { + if (CommDebuggingIsOn) + { + Debug.Console(1, this, "Sending: '{0}'", command); + } + + Communication.SendText(command + Delimiter); + } + + /// + /// Gathers responses and enqueues them. + /// + /// + /// + private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) + { + //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; + } + + + /// + /// Queues the initial queries to be sent upon connection + /// + private void SetUpSyncQueries() + { + // zStatus + _syncState.AddQueryToQueue("zStatus Call Status"); + _syncState.AddQueryToQueue("zStatus Audio Input Line"); + _syncState.AddQueryToQueue("zStatus Audio Output Line"); + _syncState.AddQueryToQueue("zStatus Video Camera Line"); + _syncState.AddQueryToQueue("zStatus Video Optimizable"); + _syncState.AddQueryToQueue("zStatus Capabilities"); + _syncState.AddQueryToQueue("zStatus Sharing"); + _syncState.AddQueryToQueue("zStatus CameraShare"); + _syncState.AddQueryToQueue("zStatus Call Layout"); + _syncState.AddQueryToQueue("zStatus Call ClosedCaption Available"); + _syncState.AddQueryToQueue("zStatus NumberOfScreens"); + + // zConfiguration + + _syncState.AddQueryToQueue("zConfiguration Call Sharing optimize_video_sharing"); + _syncState.AddQueryToQueue("zConfiguration Call Microphone Mute"); + _syncState.AddQueryToQueue("zConfiguration Call Camera Mute"); + _syncState.AddQueryToQueue("zConfiguration Audio Input SelectedId"); + _syncState.AddQueryToQueue("zConfiguration Audio Input is_sap_disabled"); + _syncState.AddQueryToQueue("zConfiguration Audio Input reduce_reverb"); + _syncState.AddQueryToQueue("zConfiguration Audio Input volume"); + _syncState.AddQueryToQueue("zConfiguration Audio Output selectedId"); + _syncState.AddQueryToQueue("zConfiguration Audio Output volume"); + _syncState.AddQueryToQueue("zConfiguration Video hide_conf_self_video"); + _syncState.AddQueryToQueue("zConfiguration Video Camera selectedId"); + _syncState.AddQueryToQueue("zConfiguration Video Camera Mirror"); + _syncState.AddQueryToQueue("zConfiguration Client appVersion"); + _syncState.AddQueryToQueue("zConfiguration Client deviceSystem"); + _syncState.AddQueryToQueue("zConfiguration Call Layout ShareThumb"); + _syncState.AddQueryToQueue("zConfiguration Call Layout Style"); + _syncState.AddQueryToQueue("zConfiguration Call Layout Size"); + _syncState.AddQueryToQueue("zConfiguration Call Layout Position"); + _syncState.AddQueryToQueue("zConfiguration Call Lock Enable"); + _syncState.AddQueryToQueue("zConfiguration Call MuteUserOnEntry Enable"); + _syncState.AddQueryToQueue("zConfiguration Call ClosedCaption FontSize "); + _syncState.AddQueryToQueue("zConfiguration Call ClosedCaption Visible"); + + // zCommand + + if (!_props.DisablePhonebookAutoDownload) + { + _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 512"); + } + + _syncState.AddQueryToQueue("zCommand Bookings List"); + _syncState.AddQueryToQueue("zCommand Call ListParticipants"); + _syncState.AddQueryToQueue("zCommand Call Info"); + + + _syncState.StartSync(); + } + + /// + /// Processes messages as they are dequeued + /// + /// + private void ProcessMessage(string message) + { + // Counts the curly braces + if (message.Contains("client_loop: send disconnect: Broken pipe")) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Error, + "Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected."); + + return; + } + + if (message.Contains('{')) + { + _jsonCurlyBraceCounter++; + } + + if (message.Contains('}')) + { + _jsonCurlyBraceCounter--; + } + + Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); + + if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) + // Check for the beginning of a new JSON message + { + _jsonFeedbackMessageIsIncoming = true; + _jsonCurlyBraceCounter = 1; // reset the counter for each new message + + _jsonMessage = new StringBuilder(); + + _jsonMessage.Append(message); + + if (CommDebuggingIsOn) + { + Debug.Console(2, this, "Incoming JSON message..."); + } + + return; + } + if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) + // Check for the end of a JSON message + { + _jsonMessage.Append(message); + + if (_jsonCurlyBraceCounter == 0) + { + _jsonFeedbackMessageIsIncoming = false; + + if (CommDebuggingIsOn) + { + Debug.Console(2, this, "Complete JSON Received:\n{0}", _jsonMessage.ToString()); + } + + // Forward the complete message to be deserialized + DeserializeResponse(_jsonMessage.ToString()); + } + + //JsonMessage = new StringBuilder(); + return; + } + + // NOTE: This must happen after the above conditions have been checked + // Append subsequent partial JSON fragments to the string builder + if (_jsonFeedbackMessageIsIncoming) + { + _jsonMessage.Append(message); + + //Debug.Console(1, this, "Building JSON:\n{0}", JsonMessage.ToString()); + return; + } + + if (CommDebuggingIsOn) + { + Debug.Console(1, this, "Non-JSON response: '{0}'", message); + } + + _jsonCurlyBraceCounter = 0; // reset on non-JSON response + + if (!_syncState.InitialSyncComplete) + { + switch (message.Trim().ToLower()) // remove the whitespace + { + case "*r login successful": + { + _syncState.LoginMessageReceived(); + + // Fire up a thread to send the intial commands. + CrestronInvoke.BeginInvoke(o => + { + Thread.Sleep(100); + // disable echo of commands + SendText("echo off"); + Thread.Sleep(100); + // set feedback exclusions + SendText("zFeedback Register Op: ex Path: /Event/InfoResult/info/callin_country_list"); + Thread.Sleep(100); + SendText("zFeedback Register Op: ex Path: /Event/InfoResult/info/callout_country_list"); + Thread.Sleep(100); + + if (!_props.DisablePhonebookAutoDownload) + { + SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); + } + // switch to json format + SendText("format json"); + }); + + break; + } + } + } + } + + /// + /// Deserializes a JSON formatted response + /// + /// + private void DeserializeResponse(string response) + { + try + { + var trimmedResponse = response.Trim(); + + if (trimmedResponse.Length <= 0) + { + return; + } + + var message = JObject.Parse(trimmedResponse); + + var eType = + (eZoomRoomResponseType) + Enum.Parse(typeof(eZoomRoomResponseType), message["type"].Value(), true); + + var topKey = message["topKey"].Value(); + + var responseObj = message[topKey]; + + Debug.Console(1, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString()); + + switch (eType) + { + case eZoomRoomResponseType.zConfiguration: + { + switch (topKey.ToLower()) + { + case "call": + { + JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Call); + + break; + } + case "audio": + { + JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Audio); + + break; + } + case "video": + { + JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Video); + + break; + } + case "client": + { + JsonConvert.PopulateObject(responseObj.ToString(), Configuration.Client); + + break; + } + default: + { + break; + } + } + break; + } + case eZoomRoomResponseType.zCommand: + { + switch (topKey.ToLower()) + { + case "inforesult": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Info); + break; + } + case "phonebooklistresult": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); + + if (!PhonebookSyncState.InitialSyncComplete) + { + PhonebookSyncState.InitialPhonebookFoldersReceived(); + PhonebookSyncState.PhonebookRootEntriesReceived(); + PhonebookSyncState.SetPhonebookHasFolders(false); + PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); + } + + var directoryResults = + zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); + + DirectoryRoot = directoryResults; + + _currentDirectoryResult = DirectoryRoot; + + OnDirectoryResultReturned(directoryResults); + + break; + } + case "listparticipantsresult": + { + Debug.Console(1, this, "JTokenType: {0}", responseObj.Type); + + switch (responseObj.Type) + { + case JTokenType.Array: + Status.Call.Participants = + JsonConvert.DeserializeObject>( + responseObj.ToString()); + break; + case JTokenType.Object: + { + // this is a single participant event notification + + var participant = + JsonConvert.DeserializeObject( + responseObj.ToString()); + + if (participant != null) + { + switch (participant.Event) + { + case "ZRCUserChangedEventUserInfoUpdated": + case "ZRCUserChangedEventLeftMeeting": + { + var existingParticipant = + Status.Call.Participants.FirstOrDefault( + p => p.UserId.Equals(participant.UserId)); + + if (existingParticipant != null) + { + switch (participant.Event) + { + case "ZRCUserChangedEventLeftMeeting": + Status.Call.Participants.Remove(existingParticipant); + break; + case "ZRCUserChangedEventUserInfoUpdated": + JsonConvert.PopulateObject(responseObj.ToString(), + existingParticipant); + break; + } + } + } + break; + case "ZRCUserChangedEventJoinedMeeting": + Status.Call.Participants.Add(participant); + break; + } + } + } + break; + } + + var participants = + zCommand.ListParticipant.GetGenericParticipantListFromParticipantsResult( + Status.Call.Participants); + + Participants.CurrentParticipants = participants; + + PrintCurrentCallParticipants(); + + break; + } + default: + { + break; + } + } + break; + } + case eZoomRoomResponseType.zEvent: + { + switch (topKey.ToLower()) + { + case "phonebook": + { + if (responseObj["Updated Contact"] != null) + { + var updatedContact = + JsonConvert.DeserializeObject( + responseObj["Updated Contact"].ToString()); + + var existingContact = + Status.Phonebook.Contacts.FirstOrDefault(c => c.Jid.Equals(updatedContact.Jid)); + + if (existingContact != null) + { + // Update existing contact + JsonConvert.PopulateObject(responseObj["Updated Contact"].ToString(), + existingContact); + } + } + else if (responseObj["Added Contact"] != null) + { + var jToken = responseObj["Updated Contact"]; + if (jToken != null) + { + var newContact = + JsonConvert.DeserializeObject( + jToken.ToString()); + + // Add a new contact + Status.Phonebook.Contacts.Add(newContact); + } + } + + break; + } + case "bookingslistresult": + { + if (!_syncState.InitialSyncComplete) + { + _syncState.LastQueryResponseReceived(); + } + + var codecBookings = JsonConvert.DeserializeObject>( + responseObj.ToString()); + + if (codecBookings != null && codecBookings.Count > 0) + { + CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult( + codecBookings, CodecSchedule.MeetingWarningMinutes); + } + + break; + } + case "bookings updated": + { + GetBookings(); + + break; + } + case "sharingstate": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); + + SetLayout(); + + break; + } + case "incomingcallindication": + { + var incomingCall = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (incomingCall != null) + { + var newCall = new CodecActiveCallItem + { + Direction = eCodecCallDirection.Incoming, + Status = eCodecCallStatus.Ringing, + Type = eCodecCallType.Unknown, + Name = incomingCall.callerName, + Id = incomingCall.callerJID + }; + + ActiveCalls.Add(newCall); + + OnCallStatusChange(newCall); + } + + break; + } + case "treatedincomingcallindication": + { + var incomingCall = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (incomingCall != null) + { + var existingCall = + ActiveCalls.FirstOrDefault(c => c.Id.Equals(incomingCall.callerJID)); + + if (existingCall != null) + { + existingCall.Status = !incomingCall.accepted + ? eCodecCallStatus.Disconnected + : eCodecCallStatus.Connecting; + + OnCallStatusChange(existingCall); + } + + UpdateCallStatus(); + } + + break; + } + case "calldisconnect": + { + var disconnectEvent = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (disconnectEvent.Successful) + { + if (ActiveCalls.Count > 0) + { + var activeCall = ActiveCalls.FirstOrDefault(c => c.IsActiveCall); + + if (activeCall != null) + { + activeCall.Status = eCodecCallStatus.Disconnected; + + OnCallStatusChange(activeCall); + } + } + var emptyList = new List(); + Participants.CurrentParticipants = emptyList; + } + + UpdateCallStatus(); + break; + } + case "callconnecterror": + { + UpdateCallStatus(); + break; + } + case "videounmuterequest": + { + // TODO: notify room of a request to unmute video + break; + } + case "meetingneedspassword": + { + // TODO: notify user to enter a password + break; + } + case "needwaitforhost": + { + var needWait = + JsonConvert.DeserializeObject(responseObj.ToString()); + + if (needWait.Wait) + { + // TODO: notify user to wait for host + } + + break; + } + case "openvideofailforhoststop": + { + // TODO: notify user that host has disabled unmuting video + break; + } + case "updatedcallrecordinfo": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo); + + break; + } + case "phonecallstatus": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); + break; + } + case "pinstatusofscreennotification": + { + var status = responseObj.ToObject(); + + var participant = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(status.PinnedUserId)); + + if (participant != null) + { + participant.IsPinnedFb = true; + participant.ScreenIndexIsPinnedToFb = status.ScreenIndex; + } + else + { + participant = Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); + + if (participant == null) + { + Debug.Console(2, this, "no matching participant found by pinned_user_id: {0} or screen_index: {1}", status.PinnedUserId, status.ScreenIndex); + return; + } + else + { + participant.IsPinnedFb = false; + participant.ScreenIndexIsPinnedToFb = -1; + } + } + + // fire the event as we've modified the participants list + Participants.OnParticipantsChanged(); + + break; + } + default: + { + break; + } + } + break; + } + case eZoomRoomResponseType.zStatus: + { + switch (topKey.ToLower()) + { + case "login": + { + _syncState.LoginMessageReceived(); + + if (!_syncState.InitialQueryMessagesWereSent) + { + SetUpSyncQueries(); + } + + JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); + + break; + } + case "systemunit": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); + + break; + } + case "call": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Call); + + UpdateCallStatus(); + + break; + } + case "capabilities": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Capabilities); + break; + } + case "sharing": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Sharing); + + break; + } + case "numberofscreens": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.NumberOfScreens); + break; + } + case "video": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Video); + break; + } + case "camerashare": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.CameraShare); + break; + } + case "layout": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Layout); + break; + } + case "audio input line": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioInputs); + break; + } + case "audio output line": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.AudioOuputs); + break; + } + case "video camera line": + { + JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); + + if (!_syncState.CamerasHaveBeenSetUp) + { + SetUpCameras(); + } + + break; + } + default: + { + break; + } + } + + break; + } + default: + { + Debug.Console(1, "Unknown Response Type:"); + break; + } + } + } + catch (Exception ex) + { + Debug.Console(1, this, "Error Deserializing feedback: {0}", ex); + } + } + + private void SetLayout() + { + if (!_props.AutoDefaultLayouts) return; + + if ( + (Status.Call.Sharing.State == zEvent.eSharingState.Receiving || + Status.Call.Sharing.State == zEvent.eSharingState.Sending)) + { + SendText(String.Format("zconfiguration call layout style: {0}", + _props.DefaultSharingLayout)); + } + else + { + SendText(String.Format("zconfiguration call layout style: {0}", + _props.DefaultCallLayout)); + } + } + + public void PrintCurrentCallParticipants() + { + if (Debug.Level <= 0) + { + return; + } + + Debug.Console(1, this, "****************************Call Participants***************************"); + foreach (var participant in Participants.CurrentParticipants) + { + Debug.Console(1, this, "Name: {0} Audio: {1} IsHost: {2}", participant.Name, + participant.AudioMuteFb, participant.IsHost); + } + Debug.Console(1, this, "************************************************************************"); + } + + /// + /// Retrieves bookings list + /// + private void GetBookings() + { + SendText("zCommand Bookings List"); + } + + + /// + /// Updates the current call status + /// + private void UpdateCallStatus() + { + Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", + Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); + + if (Status.Call != null) + { + var callStatus = Status.Call.Status; + + // If not currently in a meeting, intialize the call object + if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING) + { + Debug.Console(1, this, "Creating new Status.Call object"); + Status.Call = new zStatus.Call { Status = callStatus }; + + SetUpCallFeedbackActions(); + } + + if (ActiveCalls.Count == 0) + { + if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING || + callStatus == zStatus.eCallStatus.IN_MEETING) + { + var newStatus = eCodecCallStatus.Unknown; + + switch (callStatus) + { + case zStatus.eCallStatus.CONNECTING_MEETING: + newStatus = eCodecCallStatus.Connecting; + break; + case zStatus.eCallStatus.IN_MEETING: + newStatus = eCodecCallStatus.Connected; + break; + } + + var newCall = new CodecActiveCallItem { Status = newStatus }; + + ActiveCalls.Add(newCall); + + Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", + Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); + + OnCallStatusChange(newCall); + } + } + else + { + var existingCall = ActiveCalls.FirstOrDefault(c => !c.Status.Equals(eCodecCallStatus.Ringing)); + + switch (callStatus) + { + case zStatus.eCallStatus.IN_MEETING: + existingCall.Status = eCodecCallStatus.Connected; + break; + case zStatus.eCallStatus.NOT_IN_MEETING: + existingCall.Status = eCodecCallStatus.Disconnected; + break; + } + + Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", + Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); + + OnCallStatusChange(existingCall); + } + } + + Debug.Console(1, this, "****************************Active Calls*********************************"); + + // Clean up any disconnected calls left in the list + for (int i = 0; i < ActiveCalls.Count; i++) + { + var call = ActiveCalls[i]; + + Debug.Console(1, this, + @"Name: {0} ID: {1} IsActive: {2} Status: {3} Direction: {4}", call.Name, call.Id, call.IsActiveCall, call.Status, call.Direction); - if (!call.IsActiveCall) - { - Debug.Console(1, this, "******Removing Inactive Call: {0}******", call.Name); - ActiveCalls.Remove(call); - } - } - Debug.Console(1, this, "**************************************************************************"); + if (!call.IsActiveCall) + { + Debug.Console(1, this, "******Removing Inactive Call: {0}******", call.Name); + ActiveCalls.Remove(call); + } + } + Debug.Console(1, this, "**************************************************************************"); - //clear participants list after call cleanup - if (ActiveCalls.Count == 0) - { - Participants.CurrentParticipants = new List(); - } - } + //clear participants list after call cleanup + if (ActiveCalls.Count == 0) + { + Participants.CurrentParticipants = new List(); + } + } - protected override void OnCallStatusChange(CodecActiveCallItem item) - { - base.OnCallStatusChange(item); + protected override void OnCallStatusChange(CodecActiveCallItem item) + { + base.OnCallStatusChange(item); - Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", - Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); + Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", + Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); - if (_props.AutoDefaultLayouts) - { - SetLayout(); - } - } + if (_props.AutoDefaultLayouts) + { + SetLayout(); + } + } - public override void StartSharing() - { - SendText("zCommand Call Sharing HDMI Start"); - } + public override void StartSharing() + { + SendText("zCommand Call Sharing HDMI Start"); + } - /// - /// Stops sharing the current presentation - /// - public override void StopSharing() - { - SendText("zCommand Call Sharing Disconnect"); - } + /// + /// Stops sharing the current presentation + /// + public override void StopSharing() + { + SendText("zCommand Call Sharing Disconnect"); + } - public override void PrivacyModeOn() - { - SendText("zConfiguration Call Microphone Mute: on"); - } + public override void PrivacyModeOn() + { + SendText("zConfiguration Call Microphone Mute: on"); + } - public override void PrivacyModeOff() - { - SendText("zConfiguration Call Microphone Mute: off"); - } + public override void PrivacyModeOff() + { + SendText("zConfiguration Call Microphone Mute: off"); + } - public override void PrivacyModeToggle() - { - if (PrivacyModeIsOnFeedback.BoolValue) - { - PrivacyModeOff(); - } - else - { - PrivacyModeOn(); - } - } + public override void PrivacyModeToggle() + { + if (PrivacyModeIsOnFeedback.BoolValue) + { + PrivacyModeOff(); + } + else + { + PrivacyModeOn(); + } + } - public override void MuteOff() - { - SetVolume((ushort) _previousVolumeLevel); - } + public override void MuteOff() + { + SetVolume((ushort)_previousVolumeLevel); + } - public override void MuteOn() - { - _previousVolumeLevel = Configuration.Audio.Output.Volume; // Store the previous level for recall + public override void MuteOn() + { + _previousVolumeLevel = Configuration.Audio.Output.Volume; // Store the previous level for recall - SetVolume(0); - } + SetVolume(0); + } - public override void MuteToggle() - { - if (MuteFeedback.BoolValue) - { - MuteOff(); - } - else - { - MuteOn(); - } - } + public override void MuteToggle() + { + if (MuteFeedback.BoolValue) + { + MuteOff(); + } + else + { + MuteOn(); + } + } - /// - /// Increments the voluem - /// - /// - public override void VolumeUp(bool pressRelease) - { - // TODO: Implment volume decrement that calls SetVolume() - } + /// + /// Increments the voluem + /// + /// + public override void VolumeUp(bool pressRelease) + { + // TODO: Implment volume decrement that calls SetVolume() + } - /// - /// Decrements the volume - /// - /// - public override void VolumeDown(bool pressRelease) - { - // TODO: Implment volume decrement that calls SetVolume() - } + /// + /// Decrements the volume + /// + /// + public override void VolumeDown(bool pressRelease) + { + // TODO: Implment volume decrement that calls SetVolume() + } - /// - /// Scales the level and sets the codec to the specified level within its range - /// - /// level from slider (0-65535 range) - public override void SetVolume(ushort level) - { - var scaledLevel = CrestronEnvironment.ScaleWithLimits(level, 65535, 0, 100, 0); - SendText(string.Format("zConfiguration Audio Output volume: {0}", scaledLevel)); - } + /// + /// Scales the level and sets the codec to the specified level within its range + /// + /// level from slider (0-65535 range) + public override void SetVolume(ushort level) + { + var scaledLevel = CrestronEnvironment.ScaleWithLimits(level, 65535, 0, 100, 0); + SendText(string.Format("zConfiguration Audio Output volume: {0}", scaledLevel)); + } - /// - /// Recalls the default volume on the codec - /// - public void VolumeSetToDefault() - { - } + /// + /// Recalls the default volume on the codec + /// + public void VolumeSetToDefault() + { + } - /// - /// - /// - public override void StandbyActivate() - { - // No corresponding function on device - } + /// + /// + /// + public override void StandbyActivate() + { + // No corresponding function on device + } - /// - /// - /// - public override void StandbyDeactivate() - { - // No corresponding function on device - } + /// + /// + /// + public override void StandbyDeactivate() + { + // No corresponding function on device + } - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new ZoomRoomJoinMap(joinStart); + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new ZoomRoomJoinMap(joinStart); - var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); - if (customJoins != null) - { - joinMap.SetCustomJoinData(customJoins); - } + if (customJoins != null) + { + joinMap.SetCustomJoinData(customJoins); + } - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } - LinkVideoCodecToApi(this, trilist, joinMap); + LinkVideoCodecToApi(this, trilist, joinMap); - LinkZoomRoomToApi(trilist, joinMap); - } + LinkZoomRoomToApi(trilist, joinMap); + } - /// - /// Links all the specific Zoom functionality to the API bridge - /// - /// - /// - public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap) - { - var layoutsCodec = this as IHasZoomRoomLayouts; - if (layoutsCodec != null) - { - layoutsCodec.AvailableLayoutsChanged += (o, a) => - { - trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery - == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery)); - trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker - == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Speaker)); - trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip - == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip)); - trilist.SetBool(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll - == (a.AvailableLayouts & zConfiguration.eLayoutStyle.ShareAll)); - }; + /// + /// Links all the specific Zoom functionality to the API bridge + /// + /// + /// + public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap) + { + var layoutsCodec = this as IHasZoomRoomLayouts; + if (layoutsCodec != null) + { + layoutsCodec.AvailableLayoutsChanged += (o, a) => + { + trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery + == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery)); + trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker + == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Speaker)); + trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip + == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip)); + trilist.SetBool(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll + == (a.AvailableLayouts & zConfiguration.eLayoutStyle.ShareAll)); - layoutsCodec.CanSwapContentWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]); - trilist.SetSigFalseAction(joinMap.SwapContentWithThumbnail.JoinNumber, () => layoutsCodec.SwapContentWithThumbnail()); - layoutsCodec.ContentSwappedWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SwapContentWithThumbnail.JoinNumber]); + // pass the names used to set the layout through the bridge + trilist.SetString(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery.ToString()); + trilist.SetString(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker.ToString()); + trilist.SetString(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip.ToString()); + trilist.SetString(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll.ToString()); + }; - layoutsCodec.LayoutViewIsOnFirstPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnFirstPage.JoinNumber]); - layoutsCodec.LayoutViewIsOnLastPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnLastPage.JoinNumber]); - trilist.SetSigFalseAction(joinMap.LayoutTurnToNextPage.JoinNumber, () => layoutsCodec.LayoutTurnNextPage()); - trilist.SetSigFalseAction(joinMap.LayoutTurnToPreviousPage.JoinNumber, () => layoutsCodec.LayoutTurnPreviousPage()); - trilist.SetSigFalseAction(joinMap.GetAvailableLayouts.JoinNumber, () => layoutsCodec.GetAvailableLayouts()); + layoutsCodec.CanSwapContentWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]); + trilist.SetSigFalseAction(joinMap.SwapContentWithThumbnail.JoinNumber, () => layoutsCodec.SwapContentWithThumbnail()); + layoutsCodec.ContentSwappedWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SwapContentWithThumbnail.JoinNumber]); - 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(1, this, "Unable to parse '{0}' to zConfiguration.eLayoutStyle: {1}", s, e); - } - }); + layoutsCodec.LayoutViewIsOnFirstPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnFirstPage.JoinNumber]); + layoutsCodec.LayoutViewIsOnLastPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnLastPage.JoinNumber]); + trilist.SetSigFalseAction(joinMap.LayoutTurnToNextPage.JoinNumber, () => layoutsCodec.LayoutTurnNextPage()); + trilist.SetSigFalseAction(joinMap.LayoutTurnToPreviousPage.JoinNumber, () => layoutsCodec.LayoutTurnPreviousPage()); + trilist.SetSigFalseAction(joinMap.GetAvailableLayouts.JoinNumber, () => layoutsCodec.GetAvailableLayouts()); - layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); - } + 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(1, this, "Unable to parse '{0}' to zConfiguration.eLayoutStyle: {1}", s, e); + } + }); - var pinCodec = this as IHasParticipantPinUnpin; + layoutsCodec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetCurrentLayout.JoinNumber]); + } + + var pinCodec = this as IHasParticipantPinUnpin; if (pinCodec != null) { pinCodec.NumberOfScreensFeedback.LinkInputSig(trilist.UShortInput[joinMap.NumberOfScreens.JoinNumber]); @@ -1771,370 +1779,370 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom // Set the value of the local property to be used when pinning a participant trilist.SetUShortSigAction(joinMap.ScreenIndexToPinUserTo.JoinNumber, (u) => ScreenIndexToPinUserTo = u); } - } - - public override void ExecuteSwitch(object selector) - { - var action = selector as Action; - if (action == null) - { - return; - } - - action(); - } - - public void AcceptCall() - { - var incomingCall = - ActiveCalls.FirstOrDefault( - c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); - - AcceptCall(incomingCall); - } - - public override void AcceptCall(CodecActiveCallItem call) - { - SendText(string.Format("zCommand Call Accept callerJID: {0}", call.Id)); - - call.Status = eCodecCallStatus.Connected; - - OnCallStatusChange(call); - - UpdateCallStatus(); - } - - public void RejectCall() - { - var incomingCall = - ActiveCalls.FirstOrDefault( - c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); - - RejectCall(incomingCall); - } - - public override void RejectCall(CodecActiveCallItem call) - { - SendText(string.Format("zCommand Call Reject callerJID: {0}", call.Id)); - - call.Status = eCodecCallStatus.Disconnected; - - OnCallStatusChange(call); - - UpdateCallStatus(); - } - - public override void Dial(Meeting meeting) - { - Debug.Console(1, this,"Dialing meeting.Id: {0} Title: {1}", meeting.Id, meeting.Title); - SendText(string.Format("zCommand Dial Start meetingNumber: {0}", meeting.Id)); - } - - public override void Dial(string number) - { - SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number)); - } - - /// - /// Invites a contact to either a new meeting (if not already in a meeting) or the current meeting. - /// Currently only invites a single user - /// - /// - public override void Dial(IInvitableContact contact) - { - var ic = contact as zStatus.ZoomDirectoryContact; - - if (ic != null) - { - Debug.Console(1, this, "Attempting to Dial (Invite): {0}", ic.Name); - - if (!IsInCall) - { - SendText(string.Format("zCommand Invite Duration: {0} user: {1}", DefaultMeetingDurationMin, - ic.ContactId)); - } - else - { - SendText(string.Format("zCommand Call invite user: {0}", ic.ContactId)); - } - } - } - - public override void EndCall(CodecActiveCallItem call) - { - SendText("zCommand Call Disconnect"); - } - - public override void EndAllCalls() - { - SendText("zCommand Call Disconnect"); - } - - public override void SendDtmf(string s) - { - SendDtmfToPhone(s); - } - - /// - /// Call when directory results are updated - /// - /// - private void OnDirectoryResultReturned(CodecDirectory result) - { - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); - - // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology - var handler = DirectoryResultReturned; - if (handler != null) - { - handler(this, new DirectoryEventArgs - { - Directory = result, - DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue - }); - } - - //PrintDirectory(result); - } - - /// - /// Builds the cameras List by using the Zoom Room zStatus.Cameras data. Could later be modified to build from config data - /// - private void SetUpCameras() - { - SelectedCameraFeedback = new StringFeedback(() => Configuration.Video.Camera.SelectedId); - - ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); - - foreach (var cam in Status.Cameras) - { - var camera = new ZoomRoomCamera(cam.id, cam.Name, this); - - Cameras.Add(camera); - - if (cam.Selected) - { - SelectedCamera = camera; - } - } - - if (IsInCall) - { - UpdateFarEndCameras(); - } - - _syncState.CamerasSetUp(); - } - - /// - /// Dynamically creates far end cameras for call participants who have far end control enabled. - /// - private void UpdateFarEndCameras() - { - // TODO: set up far end cameras for the current call - } - - #region Implementation of IHasParticipants - - public CodecParticipants Participants { get; private set; } - - #endregion - - #region IHasParticipantAudioMute Members - - public void MuteAudioForParticipant(int userId) - { - SendText(string.Format("zCommand Call MuteParticipant Mute: on Id: {0}", userId)); - } - - public void UnmuteAudioForParticipant(int userId) - { - SendText(string.Format("zCommand Call MuteParticipant Mute: off Id: {0}", userId)); - } - - public void ToggleAudioForParticipant(int userId) - { - var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); - - if (user == null) - { - Debug.Console(2, this, "Unable to find user with id: {0}", userId); - return; - } - - if (user.AudioMuteFb) - { - UnmuteAudioForParticipant(userId); - } - else - { - MuteAudioForParticipant(userId); - } - } - - #endregion - - #region IHasParticipantVideoMute Members - - public void MuteVideoForParticipant(int userId) - { - SendText(string.Format("zCommand Call MuteParticipantVideo Mute: on Id: {0}", userId)); - } - - public void UnmuteVideoForParticipant(int userId) - { - SendText(string.Format("zCommand Call MuteParticipantVideo Mute: off Id: {0}", userId)); - } - - public void ToggleVideoForParticipant(int userId) - { - var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); - - if (user == null) - { - Debug.Console(2, this, "Unable to find user with id: {0}", userId); - return; - } - - if (user.VideoMuteFb) - { - UnmuteVideoForParticipant(userId); - } - else - { - MuteVideoForParticipant(userId); - } - } - - #endregion - - #region IHasParticipantPinUnpin Members + } + + public override void ExecuteSwitch(object selector) + { + var action = selector as Action; + if (action == null) + { + return; + } + + action(); + } + + public void AcceptCall() + { + var incomingCall = + ActiveCalls.FirstOrDefault( + c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); + + AcceptCall(incomingCall); + } + + public override void AcceptCall(CodecActiveCallItem call) + { + SendText(string.Format("zCommand Call Accept callerJID: {0}", call.Id)); + + call.Status = eCodecCallStatus.Connected; + + OnCallStatusChange(call); + + UpdateCallStatus(); + } + + public void RejectCall() + { + var incomingCall = + ActiveCalls.FirstOrDefault( + c => c.Status.Equals(eCodecCallStatus.Ringing) && c.Direction.Equals(eCodecCallDirection.Incoming)); + + RejectCall(incomingCall); + } + + public override void RejectCall(CodecActiveCallItem call) + { + SendText(string.Format("zCommand Call Reject callerJID: {0}", call.Id)); + + call.Status = eCodecCallStatus.Disconnected; + + OnCallStatusChange(call); + + UpdateCallStatus(); + } + + public override void Dial(Meeting meeting) + { + Debug.Console(1, this, "Dialing meeting.Id: {0} Title: {1}", meeting.Id, meeting.Title); + SendText(string.Format("zCommand Dial Start meetingNumber: {0}", meeting.Id)); + } + + public override void Dial(string number) + { + SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number)); + } + + /// + /// Invites a contact to either a new meeting (if not already in a meeting) or the current meeting. + /// Currently only invites a single user + /// + /// + public override void Dial(IInvitableContact contact) + { + var ic = contact as zStatus.ZoomDirectoryContact; + + if (ic != null) + { + Debug.Console(1, this, "Attempting to Dial (Invite): {0}", ic.Name); + + if (!IsInCall) + { + SendText(string.Format("zCommand Invite Duration: {0} user: {1}", DefaultMeetingDurationMin, + ic.ContactId)); + } + else + { + SendText(string.Format("zCommand Call invite user: {0}", ic.ContactId)); + } + } + } + + public override void EndCall(CodecActiveCallItem call) + { + SendText("zCommand Call Disconnect"); + } + + public override void EndAllCalls() + { + SendText("zCommand Call Disconnect"); + } + + public override void SendDtmf(string s) + { + SendDtmfToPhone(s); + } + + /// + /// Call when directory results are updated + /// + /// + private void OnDirectoryResultReturned(CodecDirectory result) + { + CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + + // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology + var handler = DirectoryResultReturned; + if (handler != null) + { + handler(this, new DirectoryEventArgs + { + Directory = result, + DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue + }); + } + + //PrintDirectory(result); + } + + /// + /// Builds the cameras List by using the Zoom Room zStatus.Cameras data. Could later be modified to build from config data + /// + private void SetUpCameras() + { + SelectedCameraFeedback = new StringFeedback(() => Configuration.Video.Camera.SelectedId); + + ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); + + foreach (var cam in Status.Cameras) + { + var camera = new ZoomRoomCamera(cam.id, cam.Name, this); + + Cameras.Add(camera); + + if (cam.Selected) + { + SelectedCamera = camera; + } + } + + if (IsInCall) + { + UpdateFarEndCameras(); + } + + _syncState.CamerasSetUp(); + } + + /// + /// Dynamically creates far end cameras for call participants who have far end control enabled. + /// + private void UpdateFarEndCameras() + { + // TODO: set up far end cameras for the current call + } + + #region Implementation of IHasParticipants + + public CodecParticipants Participants { get; private set; } + + #endregion + + #region IHasParticipantAudioMute Members + + public void MuteAudioForParticipant(int userId) + { + SendText(string.Format("zCommand Call MuteParticipant Mute: on Id: {0}", userId)); + } + + public void UnmuteAudioForParticipant(int userId) + { + SendText(string.Format("zCommand Call MuteParticipant Mute: off Id: {0}", userId)); + } + + public void ToggleAudioForParticipant(int userId) + { + var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); + + if (user == null) + { + Debug.Console(2, this, "Unable to find user with id: {0}", userId); + return; + } + + if (user.AudioMuteFb) + { + UnmuteAudioForParticipant(userId); + } + else + { + MuteAudioForParticipant(userId); + } + } + + #endregion + + #region IHasParticipantVideoMute Members + + public void MuteVideoForParticipant(int userId) + { + SendText(string.Format("zCommand Call MuteParticipantVideo Mute: on Id: {0}", userId)); + } + + public void UnmuteVideoForParticipant(int userId) + { + SendText(string.Format("zCommand Call MuteParticipantVideo Mute: off Id: {0}", userId)); + } + + public void ToggleVideoForParticipant(int userId) + { + var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); + + if (user == null) + { + Debug.Console(2, this, "Unable to find user with id: {0}", userId); + return; + } + + if (user.VideoMuteFb) + { + UnmuteVideoForParticipant(userId); + } + else + { + MuteVideoForParticipant(userId); + } + } + + #endregion + + #region IHasParticipantPinUnpin Members - private Func NumberOfScreensFeedbackFunc { get { return () => Status.NumberOfScreens.NumOfScreens; } } + private Func NumberOfScreensFeedbackFunc { get { return () => Status.NumberOfScreens.NumOfScreens; } } - public IntFeedback NumberOfScreensFeedback { get; private set; } + public IntFeedback NumberOfScreensFeedback { get; private set; } - public int ScreenIndexToPinUserTo { get; private set; } + public int ScreenIndexToPinUserTo { get; private set; } - public void PinParticipant(int userId, int screenIndex) - { - SendText(string.Format("zCommand Call Pin Id: {0} Enable: on Screen: {1}", userId, screenIndex)); - } + public void PinParticipant(int userId, int screenIndex) + { + SendText(string.Format("zCommand Call Pin Id: {0} Enable: on Screen: {1}", userId, screenIndex)); + } - public void UnPinParticipant(int userId) - { - SendText(string.Format("zCommand Call Pin Id: {0} Enable: off", userId)); - } + public void UnPinParticipant(int userId) + { + SendText(string.Format("zCommand Call Pin Id: {0} Enable: off", userId)); + } - public void ToggleParticipantPinState(int userId, int screenIndex) - { - var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); + public void ToggleParticipantPinState(int userId, int screenIndex) + { + var user = Participants.CurrentParticipants.FirstOrDefault(p => p.UserId.Equals(userId)); - if(user == null) - { - Debug.Console(2, this, "Unable to find user with id: {0}", userId); - return; - } + if (user == null) + { + Debug.Console(2, this, "Unable to find user with id: {0}", userId); + return; + } - if (user.IsPinnedFb) - { - UnPinParticipant(userId); - } - else - { - PinParticipant(userId, screenIndex); - } - } + if (user.IsPinnedFb) + { + UnPinParticipant(userId); + } + else + { + PinParticipant(userId, screenIndex); + } + } - #endregion - - #region Implementation of IHasCameraOff + #endregion + + #region Implementation of IHasCameraOff - public BoolFeedback CameraIsOffFeedback { get; private set; } + public BoolFeedback CameraIsOffFeedback { get; private set; } - public void CameraOff() - { - CameraMuteOn(); - } + public void CameraOff() + { + CameraMuteOn(); + } - #endregion + #endregion - public BoolFeedback CameraIsMutedFeedback { get; private set; } + public BoolFeedback CameraIsMutedFeedback { get; private set; } - public void CameraMuteOn() - { - SendText("zConfiguration Call Camera Mute: On"); - } + public void CameraMuteOn() + { + SendText("zConfiguration Call Camera Mute: On"); + } - public void CameraMuteOff() - { - SendText("zConfiguration Call Camera Mute: Off"); - } + public void CameraMuteOff() + { + SendText("zConfiguration Call Camera Mute: Off"); + } - public void CameraMuteToggle() - { - if (CameraIsMutedFeedback.BoolValue) - CameraMuteOff(); - else - CameraMuteOn(); - } + public void CameraMuteToggle() + { + if (CameraIsMutedFeedback.BoolValue) + CameraMuteOff(); + else + CameraMuteOn(); + } - #region Implementation of IHasCameraAutoMode + #region Implementation of IHasCameraAutoMode - //Zoom doesn't support camera auto modes. Setting this to just unmute video - public void CameraAutoModeOn() - { - CameraMuteOff(); - throw new NotImplementedException("Zoom Room Doesn't support camera auto mode"); - } + //Zoom doesn't support camera auto modes. Setting this to just unmute video + public void CameraAutoModeOn() + { + CameraMuteOff(); + throw new NotImplementedException("Zoom Room Doesn't support camera auto mode"); + } - //Zoom doesn't support camera auto modes. Setting this to just unmute video - public void CameraAutoModeOff() - { - SendText("zConfiguration Call Camera Mute: Off"); - } + //Zoom doesn't support camera auto modes. Setting this to just unmute video + public void CameraAutoModeOff() + { + SendText("zConfiguration Call Camera Mute: Off"); + } - public void CameraAutoModeToggle() - { - throw new NotImplementedException("Zoom Room doesn't support camera auto mode"); - } + public void CameraAutoModeToggle() + { + throw new NotImplementedException("Zoom Room doesn't support camera auto mode"); + } - public BoolFeedback CameraAutoModeIsOnFeedback { get; private set; } + public BoolFeedback CameraAutoModeIsOnFeedback { get; private set; } - #endregion + #endregion - #region Implementation of IHasFarEndContentStatus + #region Implementation of IHasFarEndContentStatus - public BoolFeedback ReceivingContent { get; private set; } + public BoolFeedback ReceivingContent { get; private set; } - #endregion + #endregion - #region Implementation of IHasSelfviewPosition + #region Implementation of IHasSelfviewPosition - private CodecCommandWithLabel _currentSelfviewPipPosition; + private CodecCommandWithLabel _currentSelfviewPipPosition; - public StringFeedback SelfviewPipPositionFeedback { get; private set; } + public StringFeedback SelfviewPipPositionFeedback { get; private set; } - public void SelfviewPipPositionSet(CodecCommandWithLabel position) - { - SendText(String.Format("zConfiguration Call Layout Position: {0}", position.Command)); - } + public void SelfviewPipPositionSet(CodecCommandWithLabel position) + { + SendText(String.Format("zConfiguration Call Layout Position: {0}", position.Command)); + } - public void SelfviewPipPositionToggle() - { - if (_currentSelfviewPipPosition != null) - { - var nextPipPositionIndex = SelfviewPipPositions.IndexOf(_currentSelfviewPipPosition) + 1; + public void SelfviewPipPositionToggle() + { + if (_currentSelfviewPipPosition != null) + { + var nextPipPositionIndex = SelfviewPipPositions.IndexOf(_currentSelfviewPipPosition) + 1; - if (nextPipPositionIndex >= SelfviewPipPositions.Count) - // Check if we need to loop back to the first item in the list - nextPipPositionIndex = 0; + if (nextPipPositionIndex >= SelfviewPipPositions.Count) + // Check if we need to loop back to the first item in the list + nextPipPositionIndex = 0; - SelfviewPipPositionSet(SelfviewPipPositions[nextPipPositionIndex]); - } - } + SelfviewPipPositionSet(SelfviewPipPositions[nextPipPositionIndex]); + } + } - public List SelfviewPipPositions = new List() + public List SelfviewPipPositions = new List() { new CodecCommandWithLabel("UpLeft", "Center Left"), new CodecCommandWithLabel("UpRight", "Center Right"), @@ -2142,384 +2150,384 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom new CodecCommandWithLabel("DownLeft", "Lower Left") }; - private void ComputeSelfviewPipStatus() - { - _currentSelfviewPipPosition = - SelfviewPipPositions.FirstOrDefault( - p => p.Command.ToLower().Equals(Configuration.Call.Layout.Position.ToString().ToLower())); - } + private void ComputeSelfviewPipStatus() + { + _currentSelfviewPipPosition = + SelfviewPipPositions.FirstOrDefault( + p => p.Command.ToLower().Equals(Configuration.Call.Layout.Position.ToString().ToLower())); + } - #endregion + #endregion - #region Implementation of IHasPhoneDialing + #region Implementation of IHasPhoneDialing - private Func PhoneOffHookFeedbackFunc {get {return () => Status.PhoneCall.OffHook; }} - private Func CallerIdNameFeedbackFunc { get { return () => Status.PhoneCall.PeerDisplayName; } } - private Func CallerIdNumberFeedbackFunc { get { return () => Status.PhoneCall.PeerNumber; } } - - public BoolFeedback PhoneOffHookFeedback { get; private set; } - public StringFeedback CallerIdNameFeedback { get; private set; } - public StringFeedback CallerIdNumberFeedback { get; private set; } - - public void DialPhoneCall(string number) - { - SendText(String.Format("zCommand Dial PhoneCallOut Number: {0}", number)); - } - - public void EndPhoneCall() - { - SendText(String.Format("zCommand Dial PhoneHangUp CallId: {0}", Status.PhoneCall.CallId)); - } - - public void SendDtmfToPhone(string digit) - { - SendText(String.Format("zCommand SendSipDTMF CallId: {0} Key: {1}", Status.PhoneCall.CallId, digit)); - } - - #endregion - - #region IHasZoomRoomLayouts Members + private Func PhoneOffHookFeedbackFunc { get { return () => Status.PhoneCall.OffHook; } } + private Func CallerIdNameFeedbackFunc { get { return () => Status.PhoneCall.PeerDisplayName; } } + private Func CallerIdNumberFeedbackFunc { get { return () => Status.PhoneCall.PeerNumber; } } + + public BoolFeedback PhoneOffHookFeedback { get; private set; } + public StringFeedback CallerIdNameFeedback { get; private set; } + public StringFeedback CallerIdNumberFeedback { get; private set; } + + public void DialPhoneCall(string number) + { + SendText(String.Format("zCommand Dial PhoneCallOut Number: {0}", number)); + } + + public void EndPhoneCall() + { + SendText(String.Format("zCommand Dial PhoneHangUp CallId: {0}", Status.PhoneCall.CallId)); + } + + public void SendDtmfToPhone(string digit) + { + SendText(String.Format("zCommand SendSipDTMF CallId: {0} Key: {1}", Status.PhoneCall.CallId, digit)); + } + + #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 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 LastSelectedLayout { get; private set; } - public zConfiguration.eLayoutStyle AvailableLayouts { 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 - // Will need to test and confirm that this logic evaluates correctly - 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 - - } - - /// - /// Zoom Room specific info object - /// - public class ZoomRoomInfo : VideoCodecInfo - { - public ZoomRoomInfo(ZoomRoomStatus status, ZoomRoomConfiguration configuration) - { - Status = status; - Configuration = configuration; - } - - public ZoomRoomStatus Status { get; private set; } - public ZoomRoomConfiguration Configuration { get; private set; } - - public override bool AutoAnswerEnabled - { - get { return Status.SystemUnit.RoomInfo.AutoAnswerIsEnabled; } - } - - public override string E164Alias - { - get - { - if (!string.IsNullOrEmpty(Status.SystemUnit.MeetingNumber)) - { - return Status.SystemUnit.MeetingNumber; - } - return string.Empty; - } - } - - public override string H323Id - { - get - { - if (!string.IsNullOrEmpty(Status.Call.Info.meeting_list_item.third_party.h323_address)) - { - return Status.Call.Info.meeting_list_item.third_party.h323_address; - } - return string.Empty; - } - } - - public override string IpAddress - { - get - { - if (!string.IsNullOrEmpty(Status.SystemUnit.RoomInfo.AccountEmail)) - { - return Status.SystemUnit.RoomInfo.AccountEmail; - } - return string.Empty; - } - } - - public override bool MultiSiteOptionIsEnabled - { - get { return true; } - } - - public override string SipPhoneNumber - { - get - { - if (!string.IsNullOrEmpty(Status.Call.Info.dialIn)) - { - return Status.Call.Info.dialIn; - } - return string.Empty; - } - } - - public override string SipUri - { - get - { - if (!string.IsNullOrEmpty(Status.Call.Info.meeting_list_item.third_party.sip_address)) - { - return Status.Call.Info.meeting_list_item.third_party.sip_address; - } - return string.Empty; - } - } - } - - /// - /// Tracks the initial sycnronization state when establishing a new connection - /// - public class ZoomRoomSyncState : IKeyed - { - private readonly ZoomRoom _parent; - private readonly CrestronQueue _syncQueries; - private bool _initialSyncComplete; - - public ZoomRoomSyncState(string key, ZoomRoom parent) - { - _parent = parent; - Key = key; - _syncQueries = new CrestronQueue(50); - CodecDisconnected(); - } - - public bool InitialSyncComplete - { - get { return _initialSyncComplete; } - private set - { - if (value) - { - var handler = InitialSyncCompleted; - if (handler != null) - { - handler(this, new EventArgs()); - } - } - _initialSyncComplete = value; - } - } - - public bool LoginMessageWasReceived { get; private set; } - - public bool InitialQueryMessagesWereSent { get; private set; } - - public bool LastQueryResponseWasReceived { get; private set; } - - public bool CamerasHaveBeenSetUp { get; private set; } - - #region IKeyed Members - - public string Key { get; private set; } - - #endregion - - public event EventHandler InitialSyncCompleted; - - public void StartSync() - { - DequeueQueries(); - } - - private void DequeueQueries() - { - while (!_syncQueries.IsEmpty) - { - var query = _syncQueries.Dequeue(); - - _parent.SendText(query); - } - - InitialQueryMessagesSent(); - } - - public void AddQueryToQueue(string query) - { - _syncQueries.Enqueue(query); - } - - public void LoginMessageReceived() - { - LoginMessageWasReceived = true; - Debug.Console(1, this, "Login Message Received."); - CheckSyncStatus(); - } - - public void InitialQueryMessagesSent() - { - InitialQueryMessagesWereSent = true; - Debug.Console(1, this, "Query Messages Sent."); - CheckSyncStatus(); - } - - public void LastQueryResponseReceived() - { - LastQueryResponseWasReceived = true; - Debug.Console(1, this, "Last Query Response Received."); - CheckSyncStatus(); - } - - public void CamerasSetUp() - { - CamerasHaveBeenSetUp = true; - Debug.Console(1, this, "Cameras Set Up."); - CheckSyncStatus(); - } - - public void CodecDisconnected() - { - _syncQueries.Clear(); - LoginMessageWasReceived = false; - InitialQueryMessagesWereSent = false; - LastQueryResponseWasReceived = false; - CamerasHaveBeenSetUp = false; - InitialSyncComplete = false; - } - - private void CheckSyncStatus() - { - if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && - CamerasHaveBeenSetUp) - { - InitialSyncComplete = true; - Debug.Console(1, this, "Initial Codec Sync Complete!"); - } - else - { - InitialSyncComplete = false; - } - } - } - - public class ZoomRoomFactory : EssentialsDeviceFactory - { - public ZoomRoomFactory() - { - TypeNames = new List {"zoomroom"}; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new ZoomRoom Device"); - var comm = CommFactory.CreateCommForDevice(dc); - return new ZoomRoom(dc, comm); - } - } + /// + /// 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 + // Will need to test and confirm that this logic evaluates correctly + 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 + + } + + /// + /// Zoom Room specific info object + /// + public class ZoomRoomInfo : VideoCodecInfo + { + public ZoomRoomInfo(ZoomRoomStatus status, ZoomRoomConfiguration configuration) + { + Status = status; + Configuration = configuration; + } + + public ZoomRoomStatus Status { get; private set; } + public ZoomRoomConfiguration Configuration { get; private set; } + + public override bool AutoAnswerEnabled + { + get { return Status.SystemUnit.RoomInfo.AutoAnswerIsEnabled; } + } + + public override string E164Alias + { + get + { + if (!string.IsNullOrEmpty(Status.SystemUnit.MeetingNumber)) + { + return Status.SystemUnit.MeetingNumber; + } + return string.Empty; + } + } + + public override string H323Id + { + get + { + if (!string.IsNullOrEmpty(Status.Call.Info.meeting_list_item.third_party.h323_address)) + { + return Status.Call.Info.meeting_list_item.third_party.h323_address; + } + return string.Empty; + } + } + + public override string IpAddress + { + get + { + if (!string.IsNullOrEmpty(Status.SystemUnit.RoomInfo.AccountEmail)) + { + return Status.SystemUnit.RoomInfo.AccountEmail; + } + return string.Empty; + } + } + + public override bool MultiSiteOptionIsEnabled + { + get { return true; } + } + + public override string SipPhoneNumber + { + get + { + if (!string.IsNullOrEmpty(Status.Call.Info.dialIn)) + { + return Status.Call.Info.dialIn; + } + return string.Empty; + } + } + + public override string SipUri + { + get + { + if (!string.IsNullOrEmpty(Status.Call.Info.meeting_list_item.third_party.sip_address)) + { + return Status.Call.Info.meeting_list_item.third_party.sip_address; + } + return string.Empty; + } + } + } + + /// + /// Tracks the initial sycnronization state when establishing a new connection + /// + public class ZoomRoomSyncState : IKeyed + { + private readonly ZoomRoom _parent; + private readonly CrestronQueue _syncQueries; + private bool _initialSyncComplete; + + public ZoomRoomSyncState(string key, ZoomRoom parent) + { + _parent = parent; + Key = key; + _syncQueries = new CrestronQueue(50); + CodecDisconnected(); + } + + public bool InitialSyncComplete + { + get { return _initialSyncComplete; } + private set + { + if (value) + { + var handler = InitialSyncCompleted; + if (handler != null) + { + handler(this, new EventArgs()); + } + } + _initialSyncComplete = value; + } + } + + public bool LoginMessageWasReceived { get; private set; } + + public bool InitialQueryMessagesWereSent { get; private set; } + + public bool LastQueryResponseWasReceived { get; private set; } + + public bool CamerasHaveBeenSetUp { get; private set; } + + #region IKeyed Members + + public string Key { get; private set; } + + #endregion + + public event EventHandler InitialSyncCompleted; + + public void StartSync() + { + DequeueQueries(); + } + + private void DequeueQueries() + { + while (!_syncQueries.IsEmpty) + { + var query = _syncQueries.Dequeue(); + + _parent.SendText(query); + } + + InitialQueryMessagesSent(); + } + + public void AddQueryToQueue(string query) + { + _syncQueries.Enqueue(query); + } + + public void LoginMessageReceived() + { + LoginMessageWasReceived = true; + Debug.Console(1, this, "Login Message Received."); + CheckSyncStatus(); + } + + public void InitialQueryMessagesSent() + { + InitialQueryMessagesWereSent = true; + Debug.Console(1, this, "Query Messages Sent."); + CheckSyncStatus(); + } + + public void LastQueryResponseReceived() + { + LastQueryResponseWasReceived = true; + Debug.Console(1, this, "Last Query Response Received."); + CheckSyncStatus(); + } + + public void CamerasSetUp() + { + CamerasHaveBeenSetUp = true; + Debug.Console(1, this, "Cameras Set Up."); + CheckSyncStatus(); + } + + public void CodecDisconnected() + { + _syncQueries.Clear(); + LoginMessageWasReceived = false; + InitialQueryMessagesWereSent = false; + LastQueryResponseWasReceived = false; + CamerasHaveBeenSetUp = false; + InitialSyncComplete = false; + } + + private void CheckSyncStatus() + { + if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && + CamerasHaveBeenSetUp) + { + InitialSyncComplete = true; + Debug.Console(1, this, "Initial Codec Sync Complete!"); + } + else + { + InitialSyncComplete = false; + } + } + } + + public class ZoomRoomFactory : EssentialsDeviceFactory + { + public ZoomRoomFactory() + { + TypeNames = new List { "zoomroom" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new ZoomRoom Device"); + var comm = CommFactory.CreateCommForDevice(dc); + return new ZoomRoom(dc, comm); + } + } } \ No newline at end of file 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 index 61a59fff..07265d20 100644 --- 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 @@ -119,7 +119,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Description = "FB Indicates if layout 'Gallery' is available", JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital + JoinType = eJoinType.DigitalSerial }); [JoinName("LayoutSpeakerIsAvailable")] @@ -133,7 +133,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Description = "FB Indicates if layout 'Speaker' is available", JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital + JoinType = eJoinType.DigitalSerial }); [JoinName("LayoutStripIsAvailable")] @@ -147,7 +147,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Description = "FB Indicates if layout 'Strip' is available", JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital + JoinType = eJoinType.DigitalSerial }); [JoinName("LayoutShareAllIsAvailable")] @@ -161,7 +161,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Description = "FB Indicates if layout 'ShareAll' is available", JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital + JoinType = eJoinType.DigitalSerial }); //[JoinName("ParticipantAudioMuteToggleStart")] From 63853739f3b5c087c972af0d86adf2e6bd76d95f Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 11 May 2021 17:23:26 -0600 Subject: [PATCH 22/28] Updates object structure to deal with a bug in ZoomRoom 5.6.3 that responds with an incorrect object structure for the layout style property --- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 8 ++++ .../VideoCodec/ZoomRoom/ZoomRoom.cs | 41 ++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) 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 c8bfd5bf..28e232ea 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 @@ -1202,6 +1202,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { public string appVersion { get; set; } public string deviceSystem { get; set; } + + // This doesn't belong here, but there's a bug in the object structure of Zoom Room 5.6.3 that puts it here + public zConfiguration.Call Call { get; set; } + + public Client() + { + Call = new zConfiguration.Call(); + } } } 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 71882d5c..478e61ff 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 @@ -515,6 +515,33 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom } }; + // This is to deal with incorrect object structure coming back from the Zoom Room on v 5.6.3 + Configuration.Client.Call.Layout.PropertyChanged += (o,a) => + { + switch (a.PropertyName) + { + case "Position": + { + ComputeSelfviewPipStatus(); + + SelfviewPipPositionFeedback.FireUpdate(); + + break; + } + case "ShareThumb": + { + ContentSwappedWithThumbnailFeedback.FireUpdate(); + break; + } + case "Style": + { + LocalLayoutFeedback.FireUpdate(); + break; + } + + } + }; + Status.Call.Sharing.PropertyChanged += (o, a) => { if (a.PropertyName == "State") @@ -2283,7 +2310,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom #region IHasCodecLayouts Members - private Func LocalLayoutFeedbackFunc { get { return () => Configuration.Call.Layout.Style.ToString(); } } + private Func LocalLayoutFeedbackFunc + { + get + { + return () => + { + if (Configuration.Call.Layout.Style != zConfiguration.eLayoutStyle.None) + return Configuration.Call.Layout.Style.ToString(); + else + return Configuration.Client.Call.Layout.Style.ToString(); + }; + } + } public StringFeedback LocalLayoutFeedback { get; private set; } From 5fc4ff602782325faf681460dc0ae56d180d2624 Mon Sep 17 00:00:00 2001 From: Jason Alborough Date: Tue, 11 May 2021 20:28:15 -0400 Subject: [PATCH 23/28] #700 FIxes issue where ConfigWrite.UpdateDeviceConfig and UpdateRoomConfig do not write config to file --- .../Config/Essentials/ConfigWriter.cs | 14 +++++++------- .../Devices/ReconfigurableDevice.cs | 6 +----- .../Cameras/CameraBase.cs | 6 ++---- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigWriter.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigWriter.cs index b97eeafa..c6224859 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigWriter.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigWriter.cs @@ -54,11 +54,11 @@ namespace PepperDash.Essentials.Core.Config { bool success = false; - var deviceConfig = ConfigReader.ConfigObject.Devices.FindIndex(d => d.Key.Equals(config.Key)); + var deviceConfigIndex = ConfigReader.ConfigObject.Devices.FindIndex(d => d.Key.Equals(config.Key)); - if (deviceConfig >= 0) + if (deviceConfigIndex >= 0) { - ConfigReader.ConfigObject.Devices[deviceConfig] = config; + ConfigReader.ConfigObject.Devices[deviceConfigIndex] = config; Debug.Console(1, "Updated config of device: '{0}'", config.Key); @@ -74,13 +74,13 @@ namespace PepperDash.Essentials.Core.Config { bool success = false; - var deviceConfig = ConfigReader.ConfigObject.Rooms.FirstOrDefault(d => d.Key.Equals(config.Key)); + var roomConfigIndex = ConfigReader.ConfigObject.Rooms.FindIndex(d => d.Key.Equals(config.Key)); - if (deviceConfig != null) + if (roomConfigIndex >= 0) { - deviceConfig = config; + ConfigReader.ConfigObject.Rooms[roomConfigIndex] = config; - Debug.Console(1, "Updated config of device: '{0}'", config.Key); + Debug.Console(1, "Updated room of device: '{0}'", config.Key); success = true; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs index 60c8db0c..81988199 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/ReconfigurableDevice.cs @@ -54,11 +54,7 @@ namespace PepperDash.Essentials.Core.Devices Name = config.Name; } - protected virtual void WriteControlProperty(JToken controlObject) - { - Config.Properties["control"] = JToken.FromObject(controlObject); - CustomSetConfig(Config); - } + /// /// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs index edfd34cb..def22069 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs @@ -81,11 +81,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } protected CameraBase(string key, string name) : - base (new DeviceConfig{Name = name, Key = key}) + this (new DeviceConfig{Name = name, Key = key}) { - OutputPorts = new RoutingPortCollection(); - - ControlMode = eCameraControlMode.Manual; + } protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey, From ac0d5e59a072913356bbe862a6b25bb933b4a0e0 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 12 May 2021 11:27:33 -0500 Subject: [PATCH 24/28] ZoomRoom.cs, commented out Debug statement @ line 874 to remove 'JSON Curly Brace Count:' messages in console when using debug level 2. --- .../Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 478e61ff..1b8c5914 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 @@ -870,7 +870,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom _jsonCurlyBraceCounter--; } - Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); + // TODO [X] 2021-05-12, jkd: turned off to reduce console traffic + //Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) // Check for the beginning of a new JSON message From eac7c91327a00f968b1efbce2390d714a8c2eaad Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 13 May 2021 18:07:03 -0600 Subject: [PATCH 25/28] Create rfi_request.md --- .github/ISSUE_TEMPLATE/rfi_request.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/rfi_request.md diff --git a/.github/ISSUE_TEMPLATE/rfi_request.md b/.github/ISSUE_TEMPLATE/rfi_request.md new file mode 100644 index 00000000..e69ac70f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/rfi_request.md @@ -0,0 +1,26 @@ +--- +name: Request for Information +about: Request specific information about capabilities of the framework +title: "[RFI]-" +labels: RFI +assignees: '' + +--- + +**What is your request?** +Please provide as much detail as possible. + + +**What is the intended use case** +- [ ] Essentials Standalone Application +- [ ] Essentials + SIMPL Windows Hybrid + +**User Interface Requirements** +- [ ] Not Applicable (logic only) +- [ ] Smart Graphics Touchpanel +- [ ] Cisco Touch10 +- [ ] Mobile Control + + +**Additional context** +Add any other context or screenshots about the request here. From 2d36b808008976ab2e037e97fc9d45e3e3c06fb1 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 14 May 2021 15:46:12 -0600 Subject: [PATCH 26/28] Adds CH5 option --- .github/ISSUE_TEMPLATE/rfi_request.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/rfi_request.md b/.github/ISSUE_TEMPLATE/rfi_request.md index e69ac70f..8ad25ac6 100644 --- a/.github/ISSUE_TEMPLATE/rfi_request.md +++ b/.github/ISSUE_TEMPLATE/rfi_request.md @@ -17,9 +17,10 @@ Please provide as much detail as possible. **User Interface Requirements** - [ ] Not Applicable (logic only) -- [ ] Smart Graphics Touchpanel +- [ ] Crestron Smart Graphics Touchpanel - [ ] Cisco Touch10 - [ ] Mobile Control +- [ ] Crestron CH5 Touchpanel interface **Additional context** From db60f8f1be06128bd25b90a2c8b8da1daf9f5d06 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 20 May 2021 15:43:02 -0500 Subject: [PATCH 27/28] ResponseObject.cs updates: Added and tested SortParticipantListtByHandStatus method. Found an issue with HandStatus response, property names include ': ', updated JsonProperty definitions to account for issues with expected returns vs. actual returns. --- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 3097 +++++++++-------- 1 file changed, 1588 insertions(+), 1509 deletions(-) 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 28e232ea..b45810ac 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 @@ -15,1513 +15,1592 @@ using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { - public enum eZoomRoomResponseType - { - zEvent, - zStatus, - zConfiguration, - zCommand - } - - public abstract class NotifiableObject : INotifyPropertyChanged - { - #region INotifyPropertyChanged Members - - public event PropertyChangedEventHandler PropertyChanged; - - protected void NotifyPropertyChanged(string propertyName) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } - } - - #endregion - } - - /// - /// Used to track the current status of a ZoomRoom - /// - public class ZoomRoomStatus - { - public zStatus.Login Login { get; set; } - public zStatus.SystemUnit SystemUnit { get; set; } - public zStatus.Phonebook Phonebook { get; set; } - public zStatus.Call Call { get; set; } - public zStatus.Capabilities Capabilities { get; set; } - public zStatus.Sharing Sharing { get; set; } - public zStatus.NumberOfScreens NumberOfScreens { get; set; } - public zStatus.Layout Layout { get; set; } - public zStatus.Video Video { get; set; } - public zStatus.CameraShare CameraShare { get; set; } - public List AudioInputs { get; set; } - public List AudioOuputs { get; set; } - public List Cameras { get; set; } - public zEvent.PhoneCallStatus PhoneCall { get; set; } - - public ZoomRoomStatus() - { - Login = new zStatus.Login(); - SystemUnit = new zStatus.SystemUnit(); - Phonebook = new zStatus.Phonebook(); - Call = new zStatus.Call(); - Capabilities = new zStatus.Capabilities(); - Sharing = new zStatus.Sharing(); - NumberOfScreens = new zStatus.NumberOfScreens(); - Layout = new zStatus.Layout(); - Video = new zStatus.Video(); - CameraShare = new zStatus.CameraShare(); - AudioInputs = new List(); - AudioOuputs = new List(); - Cameras = new List(); - PhoneCall = new zEvent.PhoneCallStatus(); - } - } - - /// - /// Used to track the current configuration of a ZoomRoom - /// - public class ZoomRoomConfiguration - { - public zConfiguration.Call Call { get; set; } - public zConfiguration.Audio Audio { get; set; } - public zConfiguration.Video Video { get; set; } - public zConfiguration.Client Client { get; set; } - public zConfiguration.Camera Camera { get; set; } - - public ZoomRoomConfiguration() - { - Call = new zConfiguration.Call(); - Audio = new zConfiguration.Audio(); - Video = new zConfiguration.Video(); - Client = new zConfiguration.Client(); - Camera = new zConfiguration.Camera(); - } - } - - /// - /// Represents a response from a ZoomRoom system - /// - public class Response - { - public Status Status { get; set; } - public bool Sync { get; set; } - [JsonProperty("topKey")] - public string TopKey { get; set; } - [JsonProperty("type")] - public string Type { get; set; } - - public Response() - { - Status = new Status(); - } - } - - public class Status - { - [JsonProperty("message")] - public string Message { get; set; } - [JsonProperty("state")] - public string State { get; set; } - } - - - /// - /// zStatus class stucture - /// - public class zStatus - { - public class Login - { - [JsonProperty("ZAAPI Release")] - public string ZAAPIRelease { get; set; } - [JsonProperty("Zoom Room Release")] - public string ZoomRoomRelease { get; set; } - } - - public class SystemUnit - { - [JsonProperty("email")] - public string Email { get; set; } - [JsonProperty("login_type")] - public string LoginType { get; set; } - [JsonProperty("meeting_number")] - public string MeetingNumber { get; set; } - [JsonProperty("platform")] - public string Platform { get; set; } - [JsonProperty("room_info")] - public RoomInfo RoomInfo { get; set; } - [JsonProperty("room_version")] - public string RoomVersion { get; set; } - - public SystemUnit() - { - RoomInfo = new RoomInfo(); - } - } - - public class RoomInfo - { - [JsonProperty("account_email")] - public string AccountEmail { get; set; } - [JsonProperty("display_version")] - public string DisplayVersion { get; set; } - [JsonProperty("is_auto_answer_enabled")] - public bool AutoAnswerIsEnabled { get; set; } - [JsonProperty("is_auto_answer_selected")] - public bool AutoAnswerIsSelected { get; set; } - [JsonProperty("room_name")] - public string RoomName { get; set; } - } - - public class CloudPbxInfo - { - [JsonProperty("company_number")] - public string CompanyNumber { get; set; } - [JsonProperty("extension")] - public string Extension { get; set; } - [JsonProperty("isValid")] - public bool IsValid { get; set; } - } - - public enum ePresence - { - PRESENCE_OFFLINE, - PRESENCE_ONLINE, - PRESENCE_AWAY, - PRESENCE_BUSY, - PRESENCE_DND - } - - public class Contact - { - [JsonProperty("avatarURL")] - public string AvatarURL { get; set; } - [JsonProperty("cloud_pbx_info")] - public CloudPbxInfo CloudPbxInfo { get; set; } - [JsonProperty("email")] - public string Email { get; set; } - [JsonProperty("firstName")] - public string FirstName { get; set; } - [JsonProperty("index")] - public int Index { get; set; } - [JsonProperty("isLegacy")] - public bool IsLegacy { get; set; } - [JsonProperty("isZoomRoom")] - public bool IsZoomRoom { get; set; } - [JsonProperty("jid")] - public string Jid { get; set; } - [JsonProperty("lastName")] - public string LastName { get; set; } - [JsonProperty("onDesktop")] - public bool OnDesktop { get; set; } - [JsonProperty("onMobile")] - public bool OnMobile { get; set; } - [JsonProperty("phoneNumber")] - public string PhoneNumber { get; set; } - [JsonProperty("presence")] - public ePresence Presence { get; set; } - [JsonProperty("presence_status")] - public int PresenceStatus { get; set; } - [JsonProperty("screenName")] - public string ScreenName { get; set; } - [JsonProperty("sip_phone_number")] - public string SipPhoneNumber { get; set; } - - - public Contact() - { - CloudPbxInfo = new CloudPbxInfo(); - } - } - - /// - /// Used to be able to inplement IInvitableContact on DirectoryContact - /// - public class ZoomDirectoryContact : DirectoryContact, IInvitableContact - { - - } - - public class Phonebook - { - [JsonProperty("Contacts")] - public List Contacts { get; set; } - - public Phonebook() - { - Contacts = new List(); - } - - /// - /// Converts from zStatus.Contact types to generic directory items - /// - /// - public static CodecDirectory ConvertZoomContactsToGeneric(List zoomContacts) - { - var directory = new CodecDirectory(); - - var folders = new List(); - - var roomFolder = new DirectoryFolder(); - - var contactFolder = new DirectoryFolder(); - - var contacts = new List(); - - // Check if there are any zoom rooms - var zoomRooms = zoomContacts.FindAll(c => c.IsZoomRoom); - - if (zoomRooms.Count > 0) - { - // If so, setup a rooms and contacts folder and add them. - roomFolder.Name = "Rooms"; - roomFolder.ParentFolderId = "root"; - roomFolder.FolderId = "rooms"; - - contactFolder.Name = "Contacts"; - contactFolder.ParentFolderId = "root"; - contactFolder.FolderId = "contacts"; - - folders.Add(roomFolder); - folders.Add(contactFolder); - - directory.AddFoldersToDirectory(folders); - } - - try - { - if (zoomContacts.Count == 0) return directory; - { - foreach (Contact c in zoomContacts) - { - var contact = new ZoomDirectoryContact {Name = c.ScreenName, ContactId = c.Jid}; - - if (folders.Count > 0) - { - contact.ParentFolderId = c.IsZoomRoom ? "rooms" : "contacts"; - } - - contacts.Add(contact); - } - - directory.AddContactsToDirectory(contacts); - } - } - catch (Exception e) - { - Debug.Console(1, "Error converting Zoom Phonebook results to generic: {0}", e); - } - - return directory; - } - } - - public enum eCallStatus - { - UNKNOWN, - NOT_IN_MEETING, - CONNECTING_MEETING, - IN_MEETING, - LOGGED_OUT - } - - public class ClosedCaption - { - public bool Available { get; set; } - } - - public class Call : NotifiableObject - { - private eCallStatus _status; - private List _participants; - - public bool IsInCall; - - public eCallStatus Status - { - get - { - return _status; - } - set - { - if (value != _status) - { - _status = value; - IsInCall = _status == eCallStatus.IN_MEETING || _status == eCallStatus.CONNECTING_MEETING; - NotifyPropertyChanged("Status"); - } - } - } - public ClosedCaption ClosedCaption { get; set; } - public List Participants - { - get - { - return _participants; - } - set - { - _participants = value; - NotifyPropertyChanged("Participants"); - } - } - public zEvent.SharingState Sharing { get; set; } - - public CallRecordInfo CallRecordInfo { get; set; } - - private zCommand.InfoResult _info; - - public zCommand.InfoResult Info - { - get - { - return _info; - } - set - { - _info = value; - NotifyPropertyChanged("Info"); - } - } - - public Call() - { - ClosedCaption = new ClosedCaption(); - Participants = new List(); - Sharing = new zEvent.SharingState(); - CallRecordInfo = new CallRecordInfo(); - Info = new zCommand.InfoResult(); - } - } - - public class Capabilities - { - public bool aec_Setting_Stored_In_ZR { get; set; } - public bool can_Dtmf_For_Invite_By_Phone { get; set; } - public bool can_Mute_On_Entry { get; set; } - public bool can_Ringing_In_Pstn_Call { get; set; } - public bool can_Switch_To_Specific_Camera { get; set; } - public bool is_Airhost_Disabled { get; set; } - public bool pstn_Call_In_Local_resentation { get; set; } - public bool support_Claim_Host { get; set; } - public bool support_Out_Room_Display { get; set; } - public bool support_Pin_And_Spotlight { get; set; } - public bool supports_Audio_Checkup { get; set; } - public bool supports_CheckIn { get; set; } - public bool supports_Cloud_PBX { get; set; } - public bool supports_Encrypted_Connection { get; set; } - public bool supports_Expel_User_Permanently { get; set; } - public bool supports_H323_DTMF { get; set; } - public bool supports_Hdmi_Cec_Control { get; set; } - public bool supports_Highly_Reverberant_Room { get; set; } - public bool supports_Loading_Contacts_Dynamically { get; set; } - public bool supports_Loading_Participants_Dynamically { get; set; } - public bool supports_Mic_Record_Test { get; set; } - public bool supports_Multi_Share { get; set; } - public bool supports_ShareCamera { get; set; } - public bool supports_Share_For_Floating_And_Content_Only { get; set; } - public bool supports_Sip_Call_out { get; set; } - public bool supports_Software_Audio_Processing { get; set; } - public bool supports_Web_Settings_Push { get; set; } - } - - public class Sharing : NotifiableObject - { - private string _dispState; - private string _password; - - public string directPresentationPairingCode { get; set; } - /// - /// Laptop client sharing key - /// - public string directPresentationSharingKey { get; set; } - public string dispState - { - get - { - return _dispState; - } - set - { - if (value != _dispState) - { - _dispState = value; - NotifyPropertyChanged("dispState"); - } - } - } - public bool isAirHostClientConnected { get; set; } - public bool isBlackMagicConnected { get; set; } - public bool isBlackMagicDataAvailable { get; set; } - public bool isDirectPresentationConnected { get; set; } - public bool isSharingBlackMagic { get; set; } - /// - /// IOS Airplay code - /// - public string password - { - get - { - return _password; - } - set - { - if (value != _password) - { - _password = value; - NotifyPropertyChanged("password"); - } - } - } - public string serverName { get; set; } - public string wifiName { get; set; } - } - - public class NumberOfScreens : NotifiableObject - { - private int _numOfScreens; - - [JsonProperty("NumberOfCECScreens")] - public int NumOfCECScreens { get; set; } - [JsonProperty("NumberOfScreens")] - public int NumOfScreens - { - get - { - return _numOfScreens; - } - set - { - if (value != _numOfScreens) - { - _numOfScreens = value; - NotifyPropertyChanged("NumberOfScreens"); - } - } - } - } - - /// - /// AudioInputLine/AudioOutputLine/VideoCameraLine list item - /// - public class AudioVideoInputOutputLineItem - { - public string Alias { get; set; } - public string Name { get; set; } - public bool Selected { get; set; } - public bool combinedDevice { get; set; } - public string id { get; set; } - public bool manuallySelected { get; set; } - public int numberOfCombinedDevices { get; set; } - public int ptzComId { get; set; } - } - - public class Video - { - public bool Optimizable { get; set; } - } - - public class CameraShare : NotifiableObject - { - private bool _canControlCamera; - private bool _isSharing; - - [JsonProperty("can_Control_Camera")] - public bool CanControlCamera - { - get - { - return _canControlCamera; - } - set - { - if (value != _canControlCamera) - { - _canControlCamera = value; - NotifyPropertyChanged("CanControlCamera"); - } - } - } - public string id { get; set; } - public bool is_Mirrored { get; set; } - [JsonProperty("is_Sharing")] - public bool IsSharing - { - get - { - return _isSharing; - } - set - { - if (value != _isSharing) - { - _isSharing = value; - NotifyPropertyChanged("IsSharing"); - } - } - } - public int pan_Tilt_Speed { get; set; } - - } - - public class Layout : NotifiableObject - { - // backer variables - private bool _can_Switch_Speaker_View; - private bool _can_Switch_Wall_View; - private bool _can_Switch_Share_On_All_Screens; - private bool _is_In_First_Page; - private bool _is_In_Last_Page; - private string _video_type; - - - public bool can_Adjust_Floating_Video { get; set; } - public bool can_Switch_Floating_Share_Content { get; set; } - - /// - /// [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 - { - get - { - return _can_Switch_Share_On_All_Screens; - } - set - { - if (value != _can_Switch_Share_On_All_Screens) - { - _can_Switch_Share_On_All_Screens = value; - NotifyPropertyChanged("can_Switch_Share_On_All_Screens"); - } - } - } - - /// - /// [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. - /// - [JsonProperty("can_Switch_Speaker_View")] - public bool can_Switch_Speaker_View - { - get - { - return _can_Switch_Speaker_View; - } - set - { - if (value != _can_Switch_Speaker_View) - { - _can_Switch_Speaker_View = value; - NotifyPropertyChanged("can_Switch_Speaker_View"); - } - } - } - - /// - /// [on/off] On if it is possible to invoke zConfiguration Call Layout Style: Gallery, to switch to the Gallery mode, showing video participants in tiled windows: The Zoom Room shows up to a 5x5 array of tiled windows per page. - /// - [JsonProperty("can_Switch_Wall_View")] - public bool can_Switch_Wall_View - { - get - { - return _can_Switch_Wall_View; - } - set - { - if (value != _can_Switch_Wall_View) - { - _can_Switch_Wall_View = value; - NotifyPropertyChanged("can_Switch_Wall_View"); - } - } - } - - [JsonProperty("is_In_First_Page")] - public bool is_In_First_Page - { - get - { - return _is_In_First_Page; - } - set - { - if (value != _is_In_First_Page) - { - _is_In_First_Page = value; - NotifyPropertyChanged("is_In_First_Page"); - } - } - } - - [JsonProperty("is_In_Last_Page")] - public bool is_In_Last_Page - { - get - { - return _is_In_Last_Page; - } - set - { - if (value != _is_In_Last_Page) - { - _is_In_Last_Page = value; - NotifyPropertyChanged("is_In_Last_Page"); - } - } - } - - public bool is_supported { get; set; } - public int video_Count_In_Current_Page { get; set; } - - /// - /// [Gallery | Strip] Indicates which mode applies: Strip or Gallery. - /// - [JsonProperty("video_type")] - public string video_type - { - get - { - return _video_type; - } - set - { - if (value != _video_type) - { - _video_type = value; - NotifyPropertyChanged("video_type"); - } - } - } - } - - public class CallRecordInfo - { - public bool canRecord { get; set; } - public bool emailRequired { get; set; } - public bool amIRecording { get; set; } - public bool meetingIsBeingRecorded { get; set; } - } - } - - /// - /// zEvent Class Structure - /// - public class zEvent - { - public class NeedWaitForHost - { - public bool Wait { get; set; } - } - - public class IncomingCallIndication - { - public string callerJID { get; set; } - public string calleeJID { get; set; } - public string meetingID { get; set; } - public string password { get; set; } - public string meetingOption { get; set; } - public long MeetingNumber { get; set; } - public string callerName { get; set; } - public string avatarURL { get; set; } - public int lifeTime { get; set; } - public bool accepted { get; set; } - } - - public class CallConnectError - { - public int error_code { get; set; } - public string error_message { get; set; } - } - - public class CallDisconnect - { - public bool Successful - { - get - { - return success == "on"; - } - } - - public string success { get; set; } - } - - public class Layout - { - public bool Sharethumb { get; set; } - } - - public class Call - { - public Layout Layout { get; set; } - } - - public class Client - { - public Call Call { get; set; } - } - - public enum eSharingState - { - None, - Connecting, - Sending, - Receiving, - Send_Receiving - } - - public class SharingState : NotifiableObject - { - private bool _paused; - private eSharingState _state; - - public bool IsSharing; - - [JsonProperty("paused")] - public bool Paused - { - get - { - return _paused; - } - set - { - if (value != _paused) - { - _paused = value; - NotifyPropertyChanged("Paused"); - } - } - } - [JsonProperty("state")] - public eSharingState State - { - get - { - return _state; - } - set - { - if (value != _state) - { - _state = value; - IsSharing = _state == eSharingState.Sending; - NotifyPropertyChanged("State"); - } - } - } - } - - public class PinStatusOfScreenNotification - { - - - [JsonProperty("can_be_pinned")] - public bool CanBePinned { get; set; } - [JsonProperty("can_pin_share")] - public bool CanPinShare { get; set; } - [JsonProperty("pinned_share_source_id")] - public int PinnedShareSourceId { get; set; } - [JsonProperty("pinned_user_id")] - public int PinnedUserId { get; set; } - [JsonProperty("screen_index")] - public int ScreenIndex { get; set; } - [JsonProperty("screen_layout")] - public int ScreenLayout { get; set; } - [JsonProperty("share_source_type")] - public int ShareSourceType { get; set; } - [JsonProperty("why_cannot_pin_share")] - public string WhyCannotPinShare { get; set; } - } - - public class PhoneCallStatus:NotifiableObject - { - private bool _isIncomingCall; - private string _peerDisplayName; - private string _peerNumber; - - private bool _offHook; - - public string CallId { get; set; } - public bool IsIncomingCall { - get { return _isIncomingCall; } - set - { - if(value == _isIncomingCall) return; - - _isIncomingCall = value; - NotifyPropertyChanged("IsIncomingCall"); - } } - - public string PeerDisplayName - { - get { return _peerDisplayName; } - set - { - if (value == _peerDisplayName) return; - _peerDisplayName = value; - NotifyPropertyChanged("PeerDisplayName"); - } - } - - public string PeerNumber - { - get { return _peerNumber; } - set - { - if (value == _peerNumber) return; - - _peerNumber = value; - NotifyPropertyChanged("PeerNumber"); - } - } - - public string PeerUri { get; set; } - - private ePhoneCallStatus _status; - public ePhoneCallStatus Status - { - get { return _status; } - set - { - _status = value; - OffHook = _status == ePhoneCallStatus.PhoneCallStatus_Accepted || - _status == ePhoneCallStatus.PhoneCallStatus_InCall || - _status == ePhoneCallStatus.PhoneCallStatus_Init || - _status == ePhoneCallStatus.PhoneCallStatus_Ringing; - } - } - - public bool OffHook - { - get { return _offHook; } - set - { - if (value == _offHook) return; - - _offHook = value; - NotifyPropertyChanged("OffHook"); - } - } - } - - public enum ePhoneCallStatus - { - PhoneCallStatus_Ringing, - PhoneCallStatus_Terminated, - PhoneCallStatus_Accepted, - PhoneCallStatus_InCall, - PhoneCallStatus_Init, - } - } - - /// - /// zConfiguration class structure - /// - public class zConfiguration - { - public class Sharing - { - [JsonProperty("optimize_video_sharing")] - public bool OptimizeVideoSharing { get; set; } - } - - public class Camera : NotifiableObject - { - private bool _mute; - - public bool Mute - { - get { return _mute; } - set - { - Debug.Console(1, "Camera Mute response received: {0}", value); - - if (value == _mute) return; - - _mute = value; - NotifyPropertyChanged("Mute"); - } - } - } - - public class Microphone : NotifiableObject - { - private bool _mute; - - public bool Mute - { - get - { - return _mute; - } - set - { - if(value != _mute) - { - _mute = value; - NotifyPropertyChanged("Mute"); - } - } - } - } - - [Flags] - public enum eLayoutStyle - { - None = 0, - Gallery = 1, - Speaker = 2, - Strip = 4, - ShareAll = 8, - } - - public enum eLayoutSize - { - Off, - Size1, - Size2, - Size3, - Strip - } - - public enum eLayoutPosition - { - Center, - Up, - Right, - UpRight, - Down, - DownRight, - Left, - UpLeft, - DownLeft - } - - public class Layout : NotifiableObject - { - private bool _shareThumb; - private eLayoutStyle _style; - private eLayoutSize _size; - private 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 - { - if (value != _position) - { - _position = value; - NotifyPropertyChanged("Position"); - } - } - } - } - - public class Lock - { - public bool Enable { get; set; } - } - - public class ClosedCaption - { - public bool Visible { get; set; } - public int FontSize { get; set; } - } - - public class MuteUserOnEntry - { - public bool Enable { get; set; } - } - - public class Call - { - public Sharing Sharing { get; set; } - public Camera Camera { get; set; } - public Microphone Microphone { get; set; } - public Layout Layout { get; set; } - public Lock Lock { get; set; } - public MuteUserOnEntry MuteUserOnEntry { get; set; } - public ClosedCaption ClosedCaption { get; set; } - - - public Call() - { - Sharing = new Sharing(); - Camera = new Camera(); - Microphone = new Microphone(); - Layout = new Layout(); - Lock = new Lock(); - MuteUserOnEntry = new MuteUserOnEntry(); - ClosedCaption = new ClosedCaption(); - } - } - - public class Audio - { - public Input Input { get; set; } - public Output Output { get; set; } - - public Audio() - { - Input = new Input(); - Output = new Output(); - } - } - - public class Input : Output - { - [JsonProperty("reduce_reverb")] - public bool ReduceReverb { get; set; } - } - - public class Output : NotifiableObject - { - private int _volume; - - [JsonProperty("volume")] - public int Volume - { - get - { - return _volume; - } - set - { - if (value != _volume) - { - _volume = value; - NotifyPropertyChanged("Volume"); - } - } - } - [JsonProperty("selectedId")] - public string SelectedId { get; set; } - [JsonProperty("is_sap_disabled")] - public bool IsSapDisabled { get; set; } - } - - public class Video : NotifiableObject - { - private bool _hideConfSelfVideo; - - [JsonProperty("hide_conf_self_video")] - public bool HideConfSelfVideo - { - get - { - return _hideConfSelfVideo; - } - set - { - if (value != _hideConfSelfVideo) - { - _hideConfSelfVideo = value; - NotifyPropertyChanged("HideConfSelfVideo"); - } - } - } - - public VideoCamera Camera { get; set; } - - public Video() - { - Camera = new VideoCamera(); - } - } - - public class VideoCamera : NotifiableObject - { - private string _selectedId; - - [JsonProperty("selectedId")] - public string SelectedId { - get - { - return _selectedId; - } - set - { - if (value != _selectedId) - { - _selectedId = value; - NotifyPropertyChanged("SelectedId"); - } - } - - } - public bool Mirror { get; set; } - } - - public class Client - { - public string appVersion { get; set; } - public string deviceSystem { get; set; } - - // This doesn't belong here, but there's a bug in the object structure of Zoom Room 5.6.3 that puts it here - public zConfiguration.Call Call { get; set; } - - public Client() - { - Call = new zConfiguration.Call(); - } - } - - } - - /// - /// zCommand class structure - /// - public class zCommand - { - public class BookingsListResult - { - [JsonProperty("accessRole")] - public string AccessRole { get; set; } - [JsonProperty("calendarChangeKey")] - public string CalendarChangeKey { get; set; } - [JsonProperty("calendarID")] - public string CalendarId { get; set; } - [JsonProperty("checkIn")] - public bool CheckIn { get; set; } - [JsonProperty("creatorEmail")] - public string CreatorEmail { get; set; } - [JsonProperty("creatorName")] - public string CreatorName { get; set; } - [JsonProperty("endTime")] - public DateTime EndTime { get; set; } - [JsonProperty("hostName")] - public string HostName { get; set; } - [JsonProperty("isInstantMeeting")] - public bool IsInstantMeeting { get; set; } - [JsonProperty("isPrivate")] - public bool IsPrivate { get; set; } - [JsonProperty("location")] - public string Location { get; set; } - [JsonProperty("meetingName")] - public string MeetingName { get; set; } - [JsonProperty("meetingNumber")] - public string MeetingNumber { get; set; } - [JsonProperty("scheduledFrom")] - public string ScheduledFrom { get; set; } - [JsonProperty("startTime")] - public DateTime StartTime { get; set; } - [JsonProperty("third_party")] - public ThirdParty ThirdParty { get; set; } - } - - public static List GetGenericMeetingsFromBookingResult(List bookings, - int minutesBeforeMeetingStart) - { - var rv = GetGenericMeetingsFromBookingResult(bookings); - - foreach (var meeting in rv) - { - meeting.MinutesBeforeMeeting = minutesBeforeMeetingStart; - } - - return rv; - } - /// - /// Extracts the necessary meeting values from the Zoom bookings response and converts them to the generic class - /// - /// - /// - public static List GetGenericMeetingsFromBookingResult(List bookings) - { - var meetings = new List(); - - if (Debug.Level > 0) - { - Debug.Console(1, "Meetings List:\n"); - } - - foreach (var b in bookings) - { - var meeting = new Meeting(); - - if (b.MeetingNumber != null) - meeting.Id = b.MeetingNumber; - if (b.CreatorName != null) - meeting.Organizer = b.CreatorName; - if (b.MeetingName != null) - meeting.Title = b.MeetingName; - //if (b.Agenda != null) - // meeting.Agenda = b.Agenda.Value; - if (b.StartTime != null) - meeting.StartTime = b.StartTime; - if (b.EndTime != null) - meeting.EndTime = b.EndTime; - - meeting.Privacy = b.IsPrivate ? eMeetingPrivacy.Private : eMeetingPrivacy.Public; - - // No meeting.Calls data exists for Zoom Rooms. Leaving out for now. - var now = DateTime.Now; - if (meeting.StartTime < now && meeting.EndTime < now) - { - Debug.Console(1, "Skipping meeting {0}. Meeting is in the past.", meeting.Title); - continue; - } - - meetings.Add(meeting); - - if (Debug.Level > 0) - { - Debug.Console(1, "Title: {0}, ID: {1}, Organizer: {2}", meeting.Title, meeting.Id, meeting.Organizer); - Debug.Console(1, " Start Time: {0}, End Time: {1}, Duration: {2}", meeting.StartTime, meeting.EndTime, meeting.Duration); - Debug.Console(1, " Joinable: {0}\n", meeting.Joinable); - } - } - - meetings.OrderBy(m => m.StartTime); - - return meetings; - } - - public class HandStatus - { - [JsonProperty("is_raise_hand")] - public bool IsRaiseHand { get; set; } - [JsonProperty("is_valid")] - public bool IsValid { get; set; } - [JsonProperty("time_stamp")] - public string TimeStamp { get; set; } - } - - public class ListParticipant - { - [JsonProperty("audio_status state")] - public string AudioStatusState { get; set; } - [JsonProperty("audio_status type")] - public string AudioStatusType { get; set; } - [JsonProperty("avatar_url")] - public string AvatarUrl { get; set; } - [JsonProperty("camera_status am_i_controlling")] - public bool CameraStatusAmIControlling { get; set; } - [JsonProperty("camera_status can_i_request_control")] - public bool CameraStatusCanIRequestConrol { get; set; } - [JsonProperty("camera_status can_move_camera")] - public bool CameraStatusCanMoveCamera { get; set; } - [JsonProperty("camera_status can_switch_camera")] - public bool CameraStatusCanSwitchCamera { get; set; } - [JsonProperty("camera_status can_zoom_camera")] - public bool CameraStatusCanZoomCamera { get; set; } - [JsonProperty("can_edit_closed_caption")] - public bool CanEditClosedCaption { get; set; } - [JsonProperty("can_record")] - public bool CanRecord { get; set; } - [JsonProperty("event")] - public string Event { get; set; } - [JsonProperty("hand_status")] - public HandStatus HandStatus { get; set; } - [JsonProperty("isCohost")] - public bool IsCohost { get; set; } - [JsonProperty("is_client_support_closed_caption")] - public bool IsClientSupportClosedCaption { get; set; } - [JsonProperty("is_client_support_coHost")] - public bool IsClientSupportCoHost { get; set; } - [JsonProperty("is_host")] - public bool IsHost { get; set; } - [JsonProperty("is_myself")] - public bool IsMyself { get; set; } - [JsonProperty("is_recording")] - public bool IsRecording { get; set; } - [JsonProperty("is_video_can_mute_byHost")] - public bool IsVideoCanMuteByHost { get; set; } - [JsonProperty("is_video_can_unmute_byHost")] - public bool IsVideoCanUnmuteByHost { get; set; } - [JsonProperty("local_recording_disabled")] - public bool LocalRecordingDisabled { get; set; } - [JsonProperty("user_id")] - public int UserId { get; set; } - [JsonProperty("user_name")] - public string UserName { get; set; } - [JsonProperty("user_type")] - public string UserType { get; set; } - [JsonProperty("video_status has_source")] - public bool VideoStatusHasSource { get; set; } - [JsonProperty("video_status is_receiving")] - public bool VideoStatusIsReceiving { get; set; } - [JsonProperty("video_status is_sending")] - public bool VideoStatusIsSending { get; set; } - - public ListParticipant() - { - HandStatus = new HandStatus(); - } - - public static List GetGenericParticipantListFromParticipantsResult( - List participants) - { - return - participants.Select( - p => - new Participant - { - UserId = p.UserId, - Name = p.UserName, - IsHost = p.IsHost, - CanMuteVideo = p.IsVideoCanMuteByHost, - CanUnmuteVideo = p.IsVideoCanUnmuteByHost, - AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED", - VideoMuteFb = p.VideoStatusIsSending, - HandIsRaisedFb = p.HandStatus.IsValid && p.HandStatus.IsRaiseHand, - }).ToList(); - } - } - - public class CallinCountryList - { - public int code { get; set; } - public string display_number { get; set; } - public string id { get; set; } - public string name { get; set; } - public string number { get; set; } - } - - public class CalloutCountryList - { - public int code { get; set; } - public string display_number { get; set; } - public string id { get; set; } - public string name { get; set; } - public string number { get; set; } - } - - public class TollFreeCallinList - { - public int code { get; set; } - public string display_number { get; set; } - public string id { get; set; } - public string name { get; set; } - public string number { get; set; } - } - - public class Info - { - public List callin_country_list { get; set; } - public List callout_country_list { get; set; } - public List toll_free_callin_list { get; set; } - } - - public class ThirdParty - { - public string h323_address { get; set; } - public string meeting_number { get; set; } - public string service_provider { get; set; } - public string sip_address { get; set; } - } - - public class MeetingListItem - { - public string accessRole { get; set; } - public string calendarChangeKey { get; set; } - public string calendarID { get; set; } - public bool checkIn { get; set; } - public string creatorEmail { get; set; } - public string creatorName { get; set; } - public string endTime { get; set; } - public string hostName { get; set; } - public bool isInstantMeeting { get; set; } - public bool isPrivate { get; set; } - public string location { get; set; } - public string meetingName { get; set; } - public string meetingNumber { get; set; } - public string scheduledFrom { get; set; } - public string startTime { get; set; } - public ThirdParty third_party { get; set; } - - public MeetingListItem() - { - third_party = new ThirdParty(); - } - } - - public class InfoResult - { - public Info Info { get; set; } - public bool am_i_original_host { get; set; } - public string default_callin_country { get; set; } - public string dialIn { get; set; } - public string international_url { get; set; } - public string invite_email_content { get; set; } - public string invite_email_subject { get; set; } - public bool is_callin_country_list_available { get; set; } - public bool is_calling_room_system_enabled { get; set; } - public bool is_toll_free_callin_list_available { get; set; } - public bool is_view_only { get; set; } - public bool is_waiting_room { get; set; } - public bool is_webinar { get; set; } - public string meeting_id { get; set; } - public MeetingListItem meeting_list_item { get; set; } - public string meeting_password { get; set; } - public string meeting_type { get; set; } - public int my_userid { get; set; } - public int participant_id { get; set; } - public string real_meeting_id { get; set; } - public string schedule_option { get; set; } - public string schedule_option2 { get; set; } - public string support_callout_type { get; set; } - public string toll_free_number { get; set; } - public string user_type { get; set; } - - public InfoResult() - { - Info = new Info(); - meeting_list_item = new MeetingListItem(); - } - } - - public class Phonebook - { - public List Contacts { get; set; } - public int Limit { get; set; } - public int Offset { get; set; } - } - } + public enum eZoomRoomResponseType + { + zEvent, + zStatus, + zConfiguration, + zCommand + } + + public abstract class NotifiableObject : INotifyPropertyChanged + { + #region INotifyPropertyChanged Members + + public event PropertyChangedEventHandler PropertyChanged; + + protected void NotifyPropertyChanged(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + #endregion + } + + /// + /// Used to track the current status of a ZoomRoom + /// + public class ZoomRoomStatus + { + public zStatus.Login Login { get; set; } + public zStatus.SystemUnit SystemUnit { get; set; } + public zStatus.Phonebook Phonebook { get; set; } + public zStatus.Call Call { get; set; } + public zStatus.Capabilities Capabilities { get; set; } + public zStatus.Sharing Sharing { get; set; } + public zStatus.NumberOfScreens NumberOfScreens { get; set; } + public zStatus.Layout Layout { get; set; } + public zStatus.Video Video { get; set; } + public zStatus.CameraShare CameraShare { get; set; } + public List AudioInputs { get; set; } + public List AudioOuputs { get; set; } + public List Cameras { get; set; } + public zEvent.PhoneCallStatus PhoneCall { get; set; } + + public ZoomRoomStatus() + { + Login = new zStatus.Login(); + SystemUnit = new zStatus.SystemUnit(); + Phonebook = new zStatus.Phonebook(); + Call = new zStatus.Call(); + Capabilities = new zStatus.Capabilities(); + Sharing = new zStatus.Sharing(); + NumberOfScreens = new zStatus.NumberOfScreens(); + Layout = new zStatus.Layout(); + Video = new zStatus.Video(); + CameraShare = new zStatus.CameraShare(); + AudioInputs = new List(); + AudioOuputs = new List(); + Cameras = new List(); + PhoneCall = new zEvent.PhoneCallStatus(); + } + } + + /// + /// Used to track the current configuration of a ZoomRoom + /// + public class ZoomRoomConfiguration + { + public zConfiguration.Call Call { get; set; } + public zConfiguration.Audio Audio { get; set; } + public zConfiguration.Video Video { get; set; } + public zConfiguration.Client Client { get; set; } + public zConfiguration.Camera Camera { get; set; } + + public ZoomRoomConfiguration() + { + Call = new zConfiguration.Call(); + Audio = new zConfiguration.Audio(); + Video = new zConfiguration.Video(); + Client = new zConfiguration.Client(); + Camera = new zConfiguration.Camera(); + } + } + + /// + /// Represents a response from a ZoomRoom system + /// + public class Response + { + public Status Status { get; set; } + public bool Sync { get; set; } + [JsonProperty("topKey")] + public string TopKey { get; set; } + [JsonProperty("type")] + public string Type { get; set; } + + public Response() + { + Status = new Status(); + } + } + + public class Status + { + [JsonProperty("message")] + public string Message { get; set; } + [JsonProperty("state")] + public string State { get; set; } + } + + + /// + /// zStatus class stucture + /// + public class zStatus + { + public class Login + { + [JsonProperty("ZAAPI Release")] + public string ZAAPIRelease { get; set; } + [JsonProperty("Zoom Room Release")] + public string ZoomRoomRelease { get; set; } + } + + public class SystemUnit + { + [JsonProperty("email")] + public string Email { get; set; } + [JsonProperty("login_type")] + public string LoginType { get; set; } + [JsonProperty("meeting_number")] + public string MeetingNumber { get; set; } + [JsonProperty("platform")] + public string Platform { get; set; } + [JsonProperty("room_info")] + public RoomInfo RoomInfo { get; set; } + [JsonProperty("room_version")] + public string RoomVersion { get; set; } + + public SystemUnit() + { + RoomInfo = new RoomInfo(); + } + } + + public class RoomInfo + { + [JsonProperty("account_email")] + public string AccountEmail { get; set; } + [JsonProperty("display_version")] + public string DisplayVersion { get; set; } + [JsonProperty("is_auto_answer_enabled")] + public bool AutoAnswerIsEnabled { get; set; } + [JsonProperty("is_auto_answer_selected")] + public bool AutoAnswerIsSelected { get; set; } + [JsonProperty("room_name")] + public string RoomName { get; set; } + } + + public class CloudPbxInfo + { + [JsonProperty("company_number")] + public string CompanyNumber { get; set; } + [JsonProperty("extension")] + public string Extension { get; set; } + [JsonProperty("isValid")] + public bool IsValid { get; set; } + } + + public enum ePresence + { + PRESENCE_OFFLINE, + PRESENCE_ONLINE, + PRESENCE_AWAY, + PRESENCE_BUSY, + PRESENCE_DND + } + + public class Contact + { + [JsonProperty("avatarURL")] + public string AvatarURL { get; set; } + [JsonProperty("cloud_pbx_info")] + public CloudPbxInfo CloudPbxInfo { get; set; } + [JsonProperty("email")] + public string Email { get; set; } + [JsonProperty("firstName")] + public string FirstName { get; set; } + [JsonProperty("index")] + public int Index { get; set; } + [JsonProperty("isLegacy")] + public bool IsLegacy { get; set; } + [JsonProperty("isZoomRoom")] + public bool IsZoomRoom { get; set; } + [JsonProperty("jid")] + public string Jid { get; set; } + [JsonProperty("lastName")] + public string LastName { get; set; } + [JsonProperty("onDesktop")] + public bool OnDesktop { get; set; } + [JsonProperty("onMobile")] + public bool OnMobile { get; set; } + [JsonProperty("phoneNumber")] + public string PhoneNumber { get; set; } + [JsonProperty("presence")] + public ePresence Presence { get; set; } + [JsonProperty("presence_status")] + public int PresenceStatus { get; set; } + [JsonProperty("screenName")] + public string ScreenName { get; set; } + [JsonProperty("sip_phone_number")] + public string SipPhoneNumber { get; set; } + + + public Contact() + { + CloudPbxInfo = new CloudPbxInfo(); + } + } + + /// + /// Used to be able to inplement IInvitableContact on DirectoryContact + /// + public class ZoomDirectoryContact : DirectoryContact, IInvitableContact + { + + } + + public class Phonebook + { + [JsonProperty("Contacts")] + public List Contacts { get; set; } + + public Phonebook() + { + Contacts = new List(); + } + + /// + /// Converts from zStatus.Contact types to generic directory items + /// + /// + public static CodecDirectory ConvertZoomContactsToGeneric(List zoomContacts) + { + var directory = new CodecDirectory(); + + var folders = new List(); + + var roomFolder = new DirectoryFolder(); + + var contactFolder = new DirectoryFolder(); + + var contacts = new List(); + + // Check if there are any zoom rooms + var zoomRooms = zoomContacts.FindAll(c => c.IsZoomRoom); + + if (zoomRooms.Count > 0) + { + // If so, setup a rooms and contacts folder and add them. + roomFolder.Name = "Rooms"; + roomFolder.ParentFolderId = "root"; + roomFolder.FolderId = "rooms"; + + contactFolder.Name = "Contacts"; + contactFolder.ParentFolderId = "root"; + contactFolder.FolderId = "contacts"; + + folders.Add(roomFolder); + folders.Add(contactFolder); + + directory.AddFoldersToDirectory(folders); + } + + try + { + if (zoomContacts.Count == 0) return directory; + { + foreach (Contact c in zoomContacts) + { + var contact = new ZoomDirectoryContact { Name = c.ScreenName, ContactId = c.Jid }; + + if (folders.Count > 0) + { + contact.ParentFolderId = c.IsZoomRoom ? "rooms" : "contacts"; + } + + contacts.Add(contact); + } + + directory.AddContactsToDirectory(contacts); + } + } + catch (Exception e) + { + Debug.Console(1, "Error converting Zoom Phonebook results to generic: {0}", e); + } + + return directory; + } + } + + public enum eCallStatus + { + UNKNOWN, + NOT_IN_MEETING, + CONNECTING_MEETING, + IN_MEETING, + LOGGED_OUT + } + + public class ClosedCaption + { + public bool Available { get; set; } + } + + public class Call : NotifiableObject + { + private eCallStatus _status; + private List _participants; + + public bool IsInCall; + + public eCallStatus Status + { + get + { + return _status; + } + set + { + if (value != _status) + { + _status = value; + IsInCall = _status == eCallStatus.IN_MEETING || _status == eCallStatus.CONNECTING_MEETING; + NotifyPropertyChanged("Status"); + } + } + } + public ClosedCaption ClosedCaption { get; set; } + public List Participants + { + get + { + return _participants; + } + set + { + _participants = value; + NotifyPropertyChanged("Participants"); + } + } + public zEvent.SharingState Sharing { get; set; } + + public CallRecordInfo CallRecordInfo { get; set; } + + private zCommand.InfoResult _info; + + public zCommand.InfoResult Info + { + get + { + return _info; + } + set + { + _info = value; + NotifyPropertyChanged("Info"); + } + } + + public Call() + { + ClosedCaption = new ClosedCaption(); + Participants = new List(); + Sharing = new zEvent.SharingState(); + CallRecordInfo = new CallRecordInfo(); + Info = new zCommand.InfoResult(); + } + } + + public class Capabilities + { + public bool aec_Setting_Stored_In_ZR { get; set; } + public bool can_Dtmf_For_Invite_By_Phone { get; set; } + public bool can_Mute_On_Entry { get; set; } + public bool can_Ringing_In_Pstn_Call { get; set; } + public bool can_Switch_To_Specific_Camera { get; set; } + public bool is_Airhost_Disabled { get; set; } + public bool pstn_Call_In_Local_resentation { get; set; } + public bool support_Claim_Host { get; set; } + public bool support_Out_Room_Display { get; set; } + public bool support_Pin_And_Spotlight { get; set; } + public bool supports_Audio_Checkup { get; set; } + public bool supports_CheckIn { get; set; } + public bool supports_Cloud_PBX { get; set; } + public bool supports_Encrypted_Connection { get; set; } + public bool supports_Expel_User_Permanently { get; set; } + public bool supports_H323_DTMF { get; set; } + public bool supports_Hdmi_Cec_Control { get; set; } + public bool supports_Highly_Reverberant_Room { get; set; } + public bool supports_Loading_Contacts_Dynamically { get; set; } + public bool supports_Loading_Participants_Dynamically { get; set; } + public bool supports_Mic_Record_Test { get; set; } + public bool supports_Multi_Share { get; set; } + public bool supports_ShareCamera { get; set; } + public bool supports_Share_For_Floating_And_Content_Only { get; set; } + public bool supports_Sip_Call_out { get; set; } + public bool supports_Software_Audio_Processing { get; set; } + public bool supports_Web_Settings_Push { get; set; } + } + + public class Sharing : NotifiableObject + { + private string _dispState; + private string _password; + + public string directPresentationPairingCode { get; set; } + /// + /// Laptop client sharing key + /// + public string directPresentationSharingKey { get; set; } + public string dispState + { + get + { + return _dispState; + } + set + { + if (value != _dispState) + { + _dispState = value; + NotifyPropertyChanged("dispState"); + } + } + } + public bool isAirHostClientConnected { get; set; } + public bool isBlackMagicConnected { get; set; } + public bool isBlackMagicDataAvailable { get; set; } + public bool isDirectPresentationConnected { get; set; } + public bool isSharingBlackMagic { get; set; } + /// + /// IOS Airplay code + /// + public string password + { + get + { + return _password; + } + set + { + if (value != _password) + { + _password = value; + NotifyPropertyChanged("password"); + } + } + } + public string serverName { get; set; } + public string wifiName { get; set; } + } + + public class NumberOfScreens : NotifiableObject + { + private int _numOfScreens; + + [JsonProperty("NumberOfCECScreens")] + public int NumOfCECScreens { get; set; } + [JsonProperty("NumberOfScreens")] + public int NumOfScreens + { + get + { + return _numOfScreens; + } + set + { + if (value != _numOfScreens) + { + _numOfScreens = value; + NotifyPropertyChanged("NumberOfScreens"); + } + } + } + } + + /// + /// AudioInputLine/AudioOutputLine/VideoCameraLine list item + /// + public class AudioVideoInputOutputLineItem + { + public string Alias { get; set; } + public string Name { get; set; } + public bool Selected { get; set; } + public bool combinedDevice { get; set; } + public string id { get; set; } + public bool manuallySelected { get; set; } + public int numberOfCombinedDevices { get; set; } + public int ptzComId { get; set; } + } + + public class Video + { + public bool Optimizable { get; set; } + } + + public class CameraShare : NotifiableObject + { + private bool _canControlCamera; + private bool _isSharing; + + [JsonProperty("can_Control_Camera")] + public bool CanControlCamera + { + get + { + return _canControlCamera; + } + set + { + if (value != _canControlCamera) + { + _canControlCamera = value; + NotifyPropertyChanged("CanControlCamera"); + } + } + } + public string id { get; set; } + public bool is_Mirrored { get; set; } + [JsonProperty("is_Sharing")] + public bool IsSharing + { + get + { + return _isSharing; + } + set + { + if (value != _isSharing) + { + _isSharing = value; + NotifyPropertyChanged("IsSharing"); + } + } + } + public int pan_Tilt_Speed { get; set; } + + } + + public class Layout : NotifiableObject + { + // backer variables + private bool _can_Switch_Speaker_View; + private bool _can_Switch_Wall_View; + private bool _can_Switch_Share_On_All_Screens; + private bool _is_In_First_Page; + private bool _is_In_Last_Page; + private string _video_type; + + + public bool can_Adjust_Floating_Video { get; set; } + public bool can_Switch_Floating_Share_Content { get; set; } + + /// + /// [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 + { + get + { + return _can_Switch_Share_On_All_Screens; + } + set + { + if (value != _can_Switch_Share_On_All_Screens) + { + _can_Switch_Share_On_All_Screens = value; + NotifyPropertyChanged("can_Switch_Share_On_All_Screens"); + } + } + } + + /// + /// [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. + /// + [JsonProperty("can_Switch_Speaker_View")] + public bool can_Switch_Speaker_View + { + get + { + return _can_Switch_Speaker_View; + } + set + { + if (value != _can_Switch_Speaker_View) + { + _can_Switch_Speaker_View = value; + NotifyPropertyChanged("can_Switch_Speaker_View"); + } + } + } + + /// + /// [on/off] On if it is possible to invoke zConfiguration Call Layout Style: Gallery, to switch to the Gallery mode, showing video participants in tiled windows: The Zoom Room shows up to a 5x5 array of tiled windows per page. + /// + [JsonProperty("can_Switch_Wall_View")] + public bool can_Switch_Wall_View + { + get + { + return _can_Switch_Wall_View; + } + set + { + if (value != _can_Switch_Wall_View) + { + _can_Switch_Wall_View = value; + NotifyPropertyChanged("can_Switch_Wall_View"); + } + } + } + + [JsonProperty("is_In_First_Page")] + public bool is_In_First_Page + { + get + { + return _is_In_First_Page; + } + set + { + if (value != _is_In_First_Page) + { + _is_In_First_Page = value; + NotifyPropertyChanged("is_In_First_Page"); + } + } + } + + [JsonProperty("is_In_Last_Page")] + public bool is_In_Last_Page + { + get + { + return _is_In_Last_Page; + } + set + { + if (value != _is_In_Last_Page) + { + _is_In_Last_Page = value; + NotifyPropertyChanged("is_In_Last_Page"); + } + } + } + + public bool is_supported { get; set; } + public int video_Count_In_Current_Page { get; set; } + + /// + /// [Gallery | Strip] Indicates which mode applies: Strip or Gallery. + /// + [JsonProperty("video_type")] + public string video_type + { + get + { + return _video_type; + } + set + { + if (value != _video_type) + { + _video_type = value; + NotifyPropertyChanged("video_type"); + } + } + } + } + + public class CallRecordInfo + { + public bool canRecord { get; set; } + public bool emailRequired { get; set; } + public bool amIRecording { get; set; } + public bool meetingIsBeingRecorded { get; set; } + } + } + + /// + /// zEvent Class Structure + /// + public class zEvent + { + public class NeedWaitForHost + { + public bool Wait { get; set; } + } + + public class IncomingCallIndication + { + public string callerJID { get; set; } + public string calleeJID { get; set; } + public string meetingID { get; set; } + public string password { get; set; } + public string meetingOption { get; set; } + public long MeetingNumber { get; set; } + public string callerName { get; set; } + public string avatarURL { get; set; } + public int lifeTime { get; set; } + public bool accepted { get; set; } + } + + public class CallConnectError + { + public int error_code { get; set; } + public string error_message { get; set; } + } + + public class CallDisconnect + { + public bool Successful + { + get + { + return success == "on"; + } + } + + public string success { get; set; } + } + + public class Layout + { + public bool Sharethumb { get; set; } + } + + public class Call + { + public Layout Layout { get; set; } + } + + public class Client + { + public Call Call { get; set; } + } + + public enum eSharingState + { + None, + Connecting, + Sending, + Receiving, + Send_Receiving + } + + public class SharingState : NotifiableObject + { + private bool _paused; + private eSharingState _state; + + public bool IsSharing; + + [JsonProperty("paused")] + public bool Paused + { + get + { + return _paused; + } + set + { + if (value != _paused) + { + _paused = value; + NotifyPropertyChanged("Paused"); + } + } + } + [JsonProperty("state")] + public eSharingState State + { + get + { + return _state; + } + set + { + if (value != _state) + { + _state = value; + IsSharing = _state == eSharingState.Sending; + NotifyPropertyChanged("State"); + } + } + } + } + + public class PinStatusOfScreenNotification + { + + + [JsonProperty("can_be_pinned")] + public bool CanBePinned { get; set; } + [JsonProperty("can_pin_share")] + public bool CanPinShare { get; set; } + [JsonProperty("pinned_share_source_id")] + public int PinnedShareSourceId { get; set; } + [JsonProperty("pinned_user_id")] + public int PinnedUserId { get; set; } + [JsonProperty("screen_index")] + public int ScreenIndex { get; set; } + [JsonProperty("screen_layout")] + public int ScreenLayout { get; set; } + [JsonProperty("share_source_type")] + public int ShareSourceType { get; set; } + [JsonProperty("why_cannot_pin_share")] + public string WhyCannotPinShare { get; set; } + } + + public class PhoneCallStatus : NotifiableObject + { + private bool _isIncomingCall; + private string _peerDisplayName; + private string _peerNumber; + + private bool _offHook; + + public string CallId { get; set; } + public bool IsIncomingCall + { + get { return _isIncomingCall; } + set + { + if (value == _isIncomingCall) return; + + _isIncomingCall = value; + NotifyPropertyChanged("IsIncomingCall"); + } + } + + public string PeerDisplayName + { + get { return _peerDisplayName; } + set + { + if (value == _peerDisplayName) return; + _peerDisplayName = value; + NotifyPropertyChanged("PeerDisplayName"); + } + } + + public string PeerNumber + { + get { return _peerNumber; } + set + { + if (value == _peerNumber) return; + + _peerNumber = value; + NotifyPropertyChanged("PeerNumber"); + } + } + + public string PeerUri { get; set; } + + private ePhoneCallStatus _status; + public ePhoneCallStatus Status + { + get { return _status; } + set + { + _status = value; + OffHook = _status == ePhoneCallStatus.PhoneCallStatus_Accepted || + _status == ePhoneCallStatus.PhoneCallStatus_InCall || + _status == ePhoneCallStatus.PhoneCallStatus_Init || + _status == ePhoneCallStatus.PhoneCallStatus_Ringing; + } + } + + public bool OffHook + { + get { return _offHook; } + set + { + if (value == _offHook) return; + + _offHook = value; + NotifyPropertyChanged("OffHook"); + } + } + } + + public enum ePhoneCallStatus + { + PhoneCallStatus_Ringing, + PhoneCallStatus_Terminated, + PhoneCallStatus_Accepted, + PhoneCallStatus_InCall, + PhoneCallStatus_Init, + } + } + + /// + /// zConfiguration class structure + /// + public class zConfiguration + { + public class Sharing + { + [JsonProperty("optimize_video_sharing")] + public bool OptimizeVideoSharing { get; set; } + } + + public class Camera : NotifiableObject + { + private bool _mute; + + public bool Mute + { + get { return _mute; } + set + { + Debug.Console(1, "Camera Mute response received: {0}", value); + + if (value == _mute) return; + + _mute = value; + NotifyPropertyChanged("Mute"); + } + } + } + + public class Microphone : NotifiableObject + { + private bool _mute; + + public bool Mute + { + get + { + return _mute; + } + set + { + if (value != _mute) + { + _mute = value; + NotifyPropertyChanged("Mute"); + } + } + } + } + + [Flags] + public enum eLayoutStyle + { + None = 0, + Gallery = 1, + Speaker = 2, + Strip = 4, + ShareAll = 8, + } + + public enum eLayoutSize + { + Off, + Size1, + Size2, + Size3, + Strip + } + + public enum eLayoutPosition + { + Center, + Up, + Right, + UpRight, + Down, + DownRight, + Left, + UpLeft, + DownLeft + } + + public class Layout : NotifiableObject + { + private bool _shareThumb; + private eLayoutStyle _style; + private eLayoutSize _size; + private 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 + { + if (value != _position) + { + _position = value; + NotifyPropertyChanged("Position"); + } + } + } + } + + public class Lock + { + public bool Enable { get; set; } + } + + public class ClosedCaption + { + public bool Visible { get; set; } + public int FontSize { get; set; } + } + + public class MuteUserOnEntry + { + public bool Enable { get; set; } + } + + public class Call + { + public Sharing Sharing { get; set; } + public Camera Camera { get; set; } + public Microphone Microphone { get; set; } + public Layout Layout { get; set; } + public Lock Lock { get; set; } + public MuteUserOnEntry MuteUserOnEntry { get; set; } + public ClosedCaption ClosedCaption { get; set; } + + + public Call() + { + Sharing = new Sharing(); + Camera = new Camera(); + Microphone = new Microphone(); + Layout = new Layout(); + Lock = new Lock(); + MuteUserOnEntry = new MuteUserOnEntry(); + ClosedCaption = new ClosedCaption(); + } + } + + public class Audio + { + public Input Input { get; set; } + public Output Output { get; set; } + + public Audio() + { + Input = new Input(); + Output = new Output(); + } + } + + public class Input : Output + { + [JsonProperty("reduce_reverb")] + public bool ReduceReverb { get; set; } + } + + public class Output : NotifiableObject + { + private int _volume; + + [JsonProperty("volume")] + public int Volume + { + get + { + return _volume; + } + set + { + if (value != _volume) + { + _volume = value; + NotifyPropertyChanged("Volume"); + } + } + } + [JsonProperty("selectedId")] + public string SelectedId { get; set; } + [JsonProperty("is_sap_disabled")] + public bool IsSapDisabled { get; set; } + } + + public class Video : NotifiableObject + { + private bool _hideConfSelfVideo; + + [JsonProperty("hide_conf_self_video")] + public bool HideConfSelfVideo + { + get + { + return _hideConfSelfVideo; + } + set + { + if (value != _hideConfSelfVideo) + { + _hideConfSelfVideo = value; + NotifyPropertyChanged("HideConfSelfVideo"); + } + } + } + + public VideoCamera Camera { get; set; } + + public Video() + { + Camera = new VideoCamera(); + } + } + + public class VideoCamera : NotifiableObject + { + private string _selectedId; + + [JsonProperty("selectedId")] + public string SelectedId + { + get + { + return _selectedId; + } + set + { + if (value != _selectedId) + { + _selectedId = value; + NotifyPropertyChanged("SelectedId"); + } + } + + } + public bool Mirror { get; set; } + } + + public class Client + { + public string appVersion { get; set; } + public string deviceSystem { get; set; } + + // This doesn't belong here, but there's a bug in the object structure of Zoom Room 5.6.3 that puts it here + public zConfiguration.Call Call { get; set; } + + public Client() + { + Call = new zConfiguration.Call(); + } + } + + } + + /// + /// zCommand class structure + /// + public class zCommand + { + public class BookingsListResult + { + [JsonProperty("accessRole")] + public string AccessRole { get; set; } + [JsonProperty("calendarChangeKey")] + public string CalendarChangeKey { get; set; } + [JsonProperty("calendarID")] + public string CalendarId { get; set; } + [JsonProperty("checkIn")] + public bool CheckIn { get; set; } + [JsonProperty("creatorEmail")] + public string CreatorEmail { get; set; } + [JsonProperty("creatorName")] + public string CreatorName { get; set; } + [JsonProperty("endTime")] + public DateTime EndTime { get; set; } + [JsonProperty("hostName")] + public string HostName { get; set; } + [JsonProperty("isInstantMeeting")] + public bool IsInstantMeeting { get; set; } + [JsonProperty("isPrivate")] + public bool IsPrivate { get; set; } + [JsonProperty("location")] + public string Location { get; set; } + [JsonProperty("meetingName")] + public string MeetingName { get; set; } + [JsonProperty("meetingNumber")] + public string MeetingNumber { get; set; } + [JsonProperty("scheduledFrom")] + public string ScheduledFrom { get; set; } + [JsonProperty("startTime")] + public DateTime StartTime { get; set; } + [JsonProperty("third_party")] + public ThirdParty ThirdParty { get; set; } + } + + public static List GetGenericMeetingsFromBookingResult(List bookings, + int minutesBeforeMeetingStart) + { + var rv = GetGenericMeetingsFromBookingResult(bookings); + + foreach (var meeting in rv) + { + meeting.MinutesBeforeMeeting = minutesBeforeMeetingStart; + } + + return rv; + } + /// + /// Extracts the necessary meeting values from the Zoom bookings response and converts them to the generic class + /// + /// + /// + public static List GetGenericMeetingsFromBookingResult(List bookings) + { + var meetings = new List(); + + if (Debug.Level > 0) + { + Debug.Console(1, "Meetings List:\n"); + } + + foreach (var b in bookings) + { + var meeting = new Meeting(); + + if (b.MeetingNumber != null) + meeting.Id = b.MeetingNumber; + if (b.CreatorName != null) + meeting.Organizer = b.CreatorName; + if (b.MeetingName != null) + meeting.Title = b.MeetingName; + //if (b.Agenda != null) + // meeting.Agenda = b.Agenda.Value; + if (b.StartTime != null) + meeting.StartTime = b.StartTime; + if (b.EndTime != null) + meeting.EndTime = b.EndTime; + + meeting.Privacy = b.IsPrivate ? eMeetingPrivacy.Private : eMeetingPrivacy.Public; + + // No meeting.Calls data exists for Zoom Rooms. Leaving out for now. + var now = DateTime.Now; + if (meeting.StartTime < now && meeting.EndTime < now) + { + Debug.Console(1, "Skipping meeting {0}. Meeting is in the past.", meeting.Title); + continue; + } + + meetings.Add(meeting); + + if (Debug.Level > 0) + { + Debug.Console(1, "Title: {0}, ID: {1}, Organizer: {2}", meeting.Title, meeting.Id, meeting.Organizer); + Debug.Console(1, " Start Time: {0}, End Time: {1}, Duration: {2}", meeting.StartTime, meeting.EndTime, meeting.Duration); + Debug.Console(1, " Joinable: {0}\n", meeting.Joinable); + } + } + + meetings.OrderBy(m => m.StartTime); + + return meetings; + } + + public class HandStatus + { + // example return of the "hand_status" object + // !!!! Note the properties contain ': ' within the property name !!! + //"hand_status": { + // "is_raise_hand: ": false, + // "is_valid: ": "on", + // "time_stamp: ": "11825083" + //}, + [JsonProperty("is_raise_hand: ")] + public bool IsRaiseHand { get; set; } + [JsonProperty("is_valid: ")] + public string IsValid { get; set; } + [JsonProperty("time_stamp: ")] + public string TimeStamp { get; set; } + /// + /// Retuns a boolean value if the participant hand state is raised and is valid (both need to be true) + /// + public bool HandIsRaisedAndValid + { + get { return IsValid != null && IsValid == "on" && IsRaiseHand; } + } + } + public class ListParticipant + { + [JsonProperty("audio_status state")] + public string AudioStatusState { get; set; } + [JsonProperty("audio_status type")] + public string AudioStatusType { get; set; } + [JsonProperty("avatar_url")] + public string AvatarUrl { get; set; } + [JsonProperty("camera_status am_i_controlling")] + public bool CameraStatusAmIControlling { get; set; } + [JsonProperty("camera_status can_i_request_control")] + public bool CameraStatusCanIRequestConrol { get; set; } + [JsonProperty("camera_status can_move_camera")] + public bool CameraStatusCanMoveCamera { get; set; } + [JsonProperty("camera_status can_switch_camera")] + public bool CameraStatusCanSwitchCamera { get; set; } + [JsonProperty("camera_status can_zoom_camera")] + public bool CameraStatusCanZoomCamera { get; set; } + [JsonProperty("can_edit_closed_caption")] + public bool CanEditClosedCaption { get; set; } + [JsonProperty("can_record")] + public bool CanRecord { get; set; } + [JsonProperty("event")] + public string Event { get; set; } + [JsonProperty("hand_status")] + public HandStatus HandStatus { get; set; } + [JsonProperty("isCohost")] + public bool IsCohost { get; set; } + [JsonProperty("is_client_support_closed_caption")] + public bool IsClientSupportClosedCaption { get; set; } + [JsonProperty("is_client_support_coHost")] + public bool IsClientSupportCoHost { get; set; } + [JsonProperty("is_host")] + public bool IsHost { get; set; } + [JsonProperty("is_myself")] + public bool IsMyself { get; set; } + [JsonProperty("is_recording")] + public bool IsRecording { get; set; } + [JsonProperty("is_video_can_mute_byHost")] + public bool IsVideoCanMuteByHost { get; set; } + [JsonProperty("is_video_can_unmute_byHost")] + public bool IsVideoCanUnmuteByHost { get; set; } + [JsonProperty("local_recording_disabled")] + public bool LocalRecordingDisabled { get; set; } + [JsonProperty("user_id")] + public int UserId { get; set; } + [JsonProperty("user_name")] + public string UserName { get; set; } + [JsonProperty("user_type")] + public string UserType { get; set; } + [JsonProperty("video_status has_source")] + public bool VideoStatusHasSource { get; set; } + [JsonProperty("video_status is_receiving")] + public bool VideoStatusIsReceiving { get; set; } + [JsonProperty("video_status is_sending")] + public bool VideoStatusIsSending { get; set; } + + public ListParticipant() + { + HandStatus = new HandStatus(); + } + + /// + /// Converts ZoomRoom pariticpant list response to an Essentials participant list + /// + /// + /// + public static List GetGenericParticipantListFromParticipantsResult( + List participants) + { + //return participants.Select(p => new Participant + // { + // UserId = p.UserId, + // Name = p.UserName, + // IsHost = p.IsHost, + // CanMuteVideo = p.IsVideoCanMuteByHost, + // CanUnmuteVideo = p.IsVideoCanUnmuteByHost, + // AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED", + // VideoMuteFb = p.VideoStatusIsSending, + // HandIsRaisedFb = p.HandStatus.HandIsRaisedAndValid, + // }).ToList(); + + var sortedParticipants = SortParticipantListByHandStatus(participants); + return sortedParticipants.Select(p => new Participant + { + UserId = p.UserId, + Name = p.UserName, + IsHost = p.IsHost, + CanMuteVideo = p.IsVideoCanMuteByHost, + CanUnmuteVideo = p.IsVideoCanUnmuteByHost, + AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED", + VideoMuteFb = p.VideoStatusIsSending, + HandIsRaisedFb = p.HandStatus.HandIsRaisedAndValid, + }).ToList(); + } + + /// + /// Will sort by hand-raise status and then alphabetically + /// + /// Zoom Room response list of participants + /// List + public static List SortParticipantListByHandStatus(List participants) + { + if (participants == null) + { + Debug.Console(1, "SortParticiapntListByHandStatu(participants == null)"); + return null; + } + + // debug testing + foreach (ListParticipant participant in participants) + { + Debug.Console(1, "{0} | IsValid: {1} | IsRaiseHand: {2} | HandIsRaisedAndValid: {3}", + participant.UserName, participant.HandStatus.IsValid, participant.HandStatus.IsRaiseHand.ToString(), participant.HandStatus.HandIsRaisedAndValid.ToString()); + } + + List handRaisedParticipantsList = participants.Where(p => p.HandStatus.HandIsRaisedAndValid).ToList(); + + if (handRaisedParticipantsList != null) + { + IOrderedEnumerable orderByDescending = handRaisedParticipantsList.OrderByDescending(p => p.HandStatus.TimeStamp); + + foreach (var participant in handRaisedParticipantsList) + Debug.Console(1, "handRaisedParticipantList: {0} | {1}", participant.UserName, participant.UserId); + } + + List allOtherParticipantsList = participants.Where(p => !p.HandStatus.HandIsRaisedAndValid).ToList(); + + if (allOtherParticipantsList != null) + { + allOtherParticipantsList.OrderBy(p => p.UserName); + + foreach (var participant in allOtherParticipantsList) + Debug.Console(1, "allOtherParticipantsList: {0} | {1}", participant.UserName, participant.UserId); + } + + // merge the lists + List sortedList = handRaisedParticipantsList.Union(allOtherParticipantsList).ToList(); + + // return the sorted list + return sortedList; + } + + } + + public class CallinCountryList + { + public int code { get; set; } + public string display_number { get; set; } + public string id { get; set; } + public string name { get; set; } + public string number { get; set; } + } + + public class CalloutCountryList + { + public int code { get; set; } + public string display_number { get; set; } + public string id { get; set; } + public string name { get; set; } + public string number { get; set; } + } + + public class TollFreeCallinList + { + public int code { get; set; } + public string display_number { get; set; } + public string id { get; set; } + public string name { get; set; } + public string number { get; set; } + } + + public class Info + { + public List callin_country_list { get; set; } + public List callout_country_list { get; set; } + public List toll_free_callin_list { get; set; } + } + + public class ThirdParty + { + public string h323_address { get; set; } + public string meeting_number { get; set; } + public string service_provider { get; set; } + public string sip_address { get; set; } + } + + public class MeetingListItem + { + public string accessRole { get; set; } + public string calendarChangeKey { get; set; } + public string calendarID { get; set; } + public bool checkIn { get; set; } + public string creatorEmail { get; set; } + public string creatorName { get; set; } + public string endTime { get; set; } + public string hostName { get; set; } + public bool isInstantMeeting { get; set; } + public bool isPrivate { get; set; } + public string location { get; set; } + public string meetingName { get; set; } + public string meetingNumber { get; set; } + public string scheduledFrom { get; set; } + public string startTime { get; set; } + public ThirdParty third_party { get; set; } + + public MeetingListItem() + { + third_party = new ThirdParty(); + } + } + + public class InfoResult + { + public Info Info { get; set; } + public bool am_i_original_host { get; set; } + public string default_callin_country { get; set; } + public string dialIn { get; set; } + public string international_url { get; set; } + public string invite_email_content { get; set; } + public string invite_email_subject { get; set; } + public bool is_callin_country_list_available { get; set; } + public bool is_calling_room_system_enabled { get; set; } + public bool is_toll_free_callin_list_available { get; set; } + public bool is_view_only { get; set; } + public bool is_waiting_room { get; set; } + public bool is_webinar { get; set; } + public string meeting_id { get; set; } + public MeetingListItem meeting_list_item { get; set; } + public string meeting_password { get; set; } + public string meeting_type { get; set; } + public int my_userid { get; set; } + public int participant_id { get; set; } + public string real_meeting_id { get; set; } + public string schedule_option { get; set; } + public string schedule_option2 { get; set; } + public string support_callout_type { get; set; } + public string toll_free_number { get; set; } + public string user_type { get; set; } + + public InfoResult() + { + Info = new Info(); + meeting_list_item = new MeetingListItem(); + } + } + + public class Phonebook + { + public List Contacts { get; set; } + public int Limit { get; set; } + public int Offset { get; set; } + } + } } \ No newline at end of file From c7cc98bff7b6498f8bcf69ab80599f3866000959 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 20 May 2021 19:32:11 -0500 Subject: [PATCH 28/28] Removed old TODO's from VideoCodecBase.cs. Marked TODO's for Issue #697. --- .../VideoCodec/Interfaces/IHasCodecLayouts.cs | 4 ++-- .../VideoCodec/VideoCodecBase.cs | 12 ++---------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 5 ++--- 3 files changed, 6 insertions(+), 15 deletions(-) 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 00787a69..a8805a21 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 @@ -27,8 +27,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { event EventHandler AvailableLayoutsChanged; - 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 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; } 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 14f23082..dc9228ce 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 @@ -673,7 +673,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, (b) => AutoShareContentWhileInCall = b); } - // TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues private List _currentMeetings = new List(); private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) @@ -685,7 +684,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec codec.CodecSchedule.MeetingWarningMinutes = i; }); - // TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues trilist.SetSigFalseAction(joinMap.DialMeeting1.JoinNumber, () => { var mtg = 1; @@ -695,7 +693,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (_currentMeetings[index] != null) Dial(_currentMeetings[index]); }); - // TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues + trilist.SetSigFalseAction(joinMap.DialMeeting2.JoinNumber, () => { var mtg = 2; @@ -705,7 +703,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (_currentMeetings[index] != null) Dial(_currentMeetings[index]); }); - // TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues + trilist.SetSigFalseAction(joinMap.DialMeeting3.JoinNumber, () => { var mtg = 3; @@ -730,14 +728,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { var currentTime = DateTime.Now; - // TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues - // - changed var currentMeetings >> field _currentMeetings - //_currentMeetings.Clear(); _currentMeetings = codec.CodecSchedule.Meetings.Where(m => m.StartTime >= currentTime || m.EndTime >= currentTime).ToList(); - // TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues - // - moved the trilist.SetSigFlaseAction(joinMap.DialMeeting1..3.JoinNumber) lambda's to LinkVideoCodecScheduleToApi - var meetingsData = UpdateMeetingsListXSig(_currentMeetings); trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count); 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 1b8c5914..2301e544 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 @@ -870,7 +870,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom _jsonCurlyBraceCounter--; } - // TODO [X] 2021-05-12, jkd: turned off to reduce console traffic //Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) @@ -2242,7 +2241,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom private void ComputeAvailableLayouts() { zConfiguration.eLayoutStyle availableLayouts = zConfiguration.eLayoutStyle.None; - // TODO: #697 [ ] Compute the avaialble layouts and set the value of AvailableLayouts + // TODO: #697 [X] Compute the avaialble layouts and set the value of AvailableLayouts // Will need to test and confirm that this logic evaluates correctly if (Status.Layout.can_Switch_Wall_View) { @@ -2291,7 +2290,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom 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 + // 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)); }