From 43f06d216786701a10edfb152f6b459b1f6e8552 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Jun 2023 14:26:52 -0500 Subject: [PATCH 01/40] feature: Add USB-C as eRoutingPortConnectionType option --- .../PepperDashEssentialsBase/Routing/RoutingPort.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs index 79dd4eda..8dc8fc4e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs @@ -42,7 +42,7 @@ namespace PepperDash.Essentials.Core public enum eRoutingPortConnectionType { None, BackplaneOnly, DisplayPort, Dvi, Hdmi, Rgb, Vga, LineAudio, DigitalAudio, Sdi, - Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming + Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming, UsbC } /// From 0ee6322684e62e1dec9b9d01a0eb0a4f3518e4e9 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Jun 2023 14:50:10 -0500 Subject: [PATCH 02/40] feature: Add USBCIn and Out Names for RoutingPortNames --- .../Routing/RoutingPortNames.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs index 00e85191..beef0dae 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs @@ -199,5 +199,37 @@ namespace PepperDash.Essentials.Core.Routing /// MediaPlayer /// public const string MediaPlayer = "mediaPlayer"; - } + /// + /// UsbCIn + /// + public const string UsbCIn = "usbCIn"; + /// + /// UsbCIn1 + /// + public const string UsbCIn1 = "usbCIn1"; + /// + /// UsbCIn2 + /// + public const string UsbCIn2 = "usbCIn2"; + /// + /// UsbCIn3 + /// + public const string UsbCIn3 = "usbCIn3"; + /// + /// UsbCOut + /// + public const string UsbCOut = "usbCOut"; + /// + /// UsbCOut1 + /// + public const string UsbCOut1 = "usbCOut1"; + /// + /// UsbCOut2 + /// + public const string UsbCOut2 = "usbCOut2"; + /// + /// UsbCOut3 + /// + public const string UsbCOut3 = "usbCOut3"; + } } \ No newline at end of file From a04bfd1fcb172d20ef73fd31a08a3bb937fadada Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Jun 2023 14:56:21 -0500 Subject: [PATCH 03/40] feature: Add HdBaseTIn and HdBaseTOut as RoutingPortNames --- .../PepperDashEssentialsBase/Routing/RoutingPortNames.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs index beef0dae..7029443b 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs @@ -231,5 +231,13 @@ namespace PepperDash.Essentials.Core.Routing /// UsbCOut3 /// public const string UsbCOut3 = "usbCOut3"; + /// + /// HdBaseTIn + /// + public const string HdBaseTIn = "hdBaseTIn"; + /// + /// HdBaseTOut + /// + public const string HdBaseTOut = "hdBaseTOut"; } } \ No newline at end of file From f4af1b6e7c853dc1df0e4f9d9319f3e64e190c8e Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Jun 2023 14:57:48 -0500 Subject: [PATCH 04/40] feature: Add HdBaseT as a eRoutingPortConnectionType --- .../PepperDashEssentialsBase/Routing/RoutingPort.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs index 8dc8fc4e..ab64f15e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs @@ -42,7 +42,7 @@ namespace PepperDash.Essentials.Core public enum eRoutingPortConnectionType { None, BackplaneOnly, DisplayPort, Dvi, Hdmi, Rgb, Vga, LineAudio, DigitalAudio, Sdi, - Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming, UsbC + Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming, UsbC, HdBaseT } /// From cab0b01a089f790c46509f0c0cd54a280b3ea93f Mon Sep 17 00:00:00 2001 From: jdevito Date: Tue, 27 Jun 2023 15:20:01 -0500 Subject: [PATCH 05/40] fix: updates systemMonitor class to append Essentials version number to the ProgramName that is passed across the bridge --- .../Monitoring/SystemMonitorController.cs | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Monitoring/SystemMonitorController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Monitoring/SystemMonitorController.cs index 319a0a3c..8a7f379a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Monitoring/SystemMonitorController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Monitoring/SystemMonitorController.cs @@ -563,11 +563,11 @@ namespace PepperDash.Essentials.Core.Monitoring ProgramUnregisteredFeedback = new BoolFeedback(() => Program.RegistrationState == eProgramRegistrationState.Unregister); ProgramUnregisteredFeedback.FireUpdate(); - - ProgramNameFeedback = new StringFeedback(() => ProgramInfo.ProgramFile); + + ProgramNameFeedback = new StringFeedback(() => ProgramInfo.ProgramFile); + CrestronDataBaseVersionFeedback = new StringFeedback(() => ProgramInfo.CrestronDb); + EnvironmentVersionFeedback = new StringFeedback(() => ProgramInfo.Environment); ProgramCompileTimeFeedback = new StringFeedback(() => ProgramInfo.CompileTime); - CrestronDataBaseVersionFeedback = new StringFeedback(() => ProgramInfo.CrestronDb); - EnvironmentVersionFeedback = new StringFeedback(() => ProgramInfo.Environment); AggregatedProgramInfoFeedback = new StringFeedback(() => JsonConvert.SerializeObject(ProgramInfo)); GetProgramInfo(); @@ -620,9 +620,9 @@ namespace PepperDash.Essentials.Core.Monitoring // Assume no valid program info. Constructing a new object will wipe all properties ProgramInfo = new ProgramInfo(Program.Number) { - OperatingState = Program.OperatingState, + OperatingState = Program.OperatingState, RegistrationState = Program.RegistrationState - }; + }; UpdateFeedbacks(); @@ -639,13 +639,20 @@ namespace PepperDash.Essentials.Core.Monitoring if (ProgramInfo.ProgramFile.Contains(".dll")) { - // SSP Program + // SSP Program ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ": ", "\n"); ProgramInfo.ApplicationName = ParseConsoleData(response, "Application Name", ": ", "\n"); ProgramInfo.ProgramTool = ParseConsoleData(response, "Program Tool", ": ", "\n"); ProgramInfo.MinFirmwareVersion = ParseConsoleData(response, "Min Firmware Version", ": ", "\n"); ProgramInfo.PlugInVersion = ParseConsoleData(response, "PlugInVersion", ": ", "\n"); + + ProgramInfo.ProgramFile += string.Format(" {0}.{1}.{2}", + ProgramInfo.CompilerRevisionInfo.Major, + ProgramInfo.CompilerRevisionInfo.Minor, + ProgramInfo.CompilerRevisionInfo.Build); + + ProgramInfo.Environment = ProgramInfo.ProgramTool; } else if (ProgramInfo.ProgramFile.Contains(".smw")) { @@ -736,6 +743,15 @@ namespace PepperDash.Essentials.Core.Monitoring [JsonProperty("compilerRevision")] public string CompilerRevision { get; set; } + [JsonIgnore] + public Version CompilerRevisionInfo + { + get + { + return new Version(CompilerRevision); + } + } + [JsonProperty("compileTime")] public string CompileTime { get; set; } @@ -776,7 +792,7 @@ namespace PepperDash.Essentials.Core.Monitoring ProgramFile = ""; FriendlyName = ""; CompilerRevision = ""; - CompileTime = ""; + CompileTime = ""; Include4Dat = ""; SystemName = ""; From 3f6b2f05a28dab2bf0e394bf70d9c4d428cf1921 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 4 Jul 2023 23:53:31 -0500 Subject: [PATCH 06/40] feature: Add Static Class to assist with getting network information about connected devices feature: Add overload to 'Contains' extension method to allow for some more verbose comparisons feature: Add 'TrimAll' string extension method to TrimStart and TrimEnd with an overload to set the character to trim docs: improve XML summary comments for string extensions --- .../Device Info/NetworkDeviceHelpers.cs | 218 ++++++++++++++++++ .../Extensions/StringExtensions.cs | 54 +++++ .../PepperDash_Essentials_Core.csproj | 1 + 3 files changed, 273 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/NetworkDeviceHelpers.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/NetworkDeviceHelpers.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/NetworkDeviceHelpers.cs new file mode 100644 index 00000000..04e697c9 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/NetworkDeviceHelpers.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using PepperDash.Core; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Core.DeviceInfo +{ + public static class NetworkDeviceHelpers + { + /// + /// Event raised when ArpTable changes + /// + public static event ArpTableEventHandler ArpTableUpdated; + + /// + /// Delegate called by ArpTableUpdated + /// + /// contains the entire ARP table and a bool to note if there was an error in retrieving the data + public delegate void ArpTableEventHandler(ArpTableEventArgs args); + + private static readonly char NewLineSplitter = CrestronEnvironment.NewLine.ToCharArray().First(); + private static readonly string NewLine = CrestronEnvironment.NewLine; + + private static readonly CCriticalSection Lock = new CCriticalSection(); + + /// + /// Last resolved ARP table - it is recommended to refresh the arp before using this. + /// + public static List ArpTable { get; private set; } + + /// + /// Force recheck of ARP table + /// + public static void RefreshArp() + { + var error = false; + try + { + Lock.Enter(); + var consoleResponse = string.Empty; + if (!CrestronConsole.SendControlSystemCommand("showarptable", ref consoleResponse)) return; + if (string.IsNullOrEmpty(consoleResponse)) + { + error = true; + return; + } + ArpTable.Clear(); + + Debug.Console(2, "ConsoleResponse of 'showarptable' : {0}{1}", NewLine, consoleResponse); + + var myLines = + consoleResponse.Split(NewLineSplitter) + .ToList() + .Where(o => (o.Contains(':') && !o.Contains("Type", StringComparison.OrdinalIgnoreCase))) + .ToList(); + foreach (var line in myLines) + { + var item = line; + var seperator = item.Contains('\t') ? '\t' : ' '; + var dataPoints = item.Split(seperator); + if (dataPoints == null || dataPoints.Length < 2) continue; + var ipAddress = SanitizeIpAddress(dataPoints.First().TrimAll()); + var macAddress = dataPoints.Last(); + ArpTable.Add(new ArpEntry(ipAddress, macAddress)); + } + } + catch (Exception ex) + { + Debug.Console(0, "Exception in \"RefreshArp\" : {0}", ex.Message); + error = true; + } + finally + { + Lock.Leave(); + OnArpTableUpdated(new ArpTableEventArgs(ArpTable, error)); + } + } + + + private static void OnArpTableUpdated(ArpTableEventArgs args) + { + if (args == null) return; + var handler = ArpTableUpdated; + if (handler == null) return; + handler.Invoke(args); + } + + static NetworkDeviceHelpers() + { + ArpTable = new List(); + } + + /// + /// Removes leading zeros, leading whitespace, and trailing whitespace from an IPAddress string + /// + /// Ip Address to Santitize + /// Sanitized Ip Address + public static string SanitizeIpAddress(string ipAddressIn) + { + try + { + var ipAddress = IPAddress.Parse(ipAddressIn.TrimStart('0')); + return ipAddress.ToString(); + } + catch (Exception ex) + { + Debug.Console(0, "Unable to Santize Ip : {0}", ex.Message); + return ipAddressIn; + } + } + + /// + /// Resolves a hostname by IP Address using DNS + /// + /// IP Address to resolve from + /// Resolved Hostname - on failure to determine hostname, will return IP Address + public static string ResolveHostnameFromIp(string ipAddress) + { + try + { + var santitizedIp = SanitizeIpAddress(ipAddress); + var hostEntry = Dns.GetHostEntry(santitizedIp); + return hostEntry == null ? ipAddress : hostEntry.HostName; + } + catch (Exception ex) + { + Debug.Console(0, "Exception Resolving Hostname from IP Address : {0}", ex.Message); + return ipAddress; + } + } + + /// + /// Resolves an IP Address by hostname using DNS + /// + /// Hostname to resolve from + /// Resolved IP Address - on a failure to determine IP Address, will return hostname + public static string ResolveIpFromHostname(string hostName) + { + try + { + var hostEntry = Dns.GetHostEntry(hostName); + return hostEntry == null ? hostName : hostEntry.AddressList.First().ToString(); + } + catch (Exception ex) + { + Debug.Console(0, "Exception Resolving IP Address from Hostname : {0}", ex.Message); + return hostName; + } + } + + } + + /// + /// Object to hold data about an arp entry + /// + public class ArpEntry + { + public readonly IPAddress IpAddress; + public readonly string MacAddress; + + /// + /// Constructs new ArpEntry object + /// + /// string formatted as ipv4 address + /// mac address string - format is unimportant + public ArpEntry(string ipAddress, string macAddress) + { + if (string.IsNullOrEmpty(ipAddress)) + { + throw new ArgumentException("\"ipAddress\" cannot be null or empty"); + } + if (string.IsNullOrEmpty(macAddress)) + { + throw new ArgumentException("\"macAddress\" cannot be null or empty"); + } + IpAddress = IPAddress.Parse(ipAddress.TrimStart().TrimStart('0').TrimEnd()); + MacAddress = macAddress; + } + } + + /// + /// Arguments passed by the ArpTableUpdated event + /// + public class ArpTableEventArgs : EventArgs + { + /// + /// The retrieved ARP Table + /// + public readonly List ArpTable; + /// + /// True if there was a problem retrieving the ARP Table + /// + public readonly bool Error; + + /// + /// Constructor for ArpTableEventArgs + /// + /// The entirety of the retrieved ARP table + /// True of an error was encountered updating the ARP table + public ArpTableEventArgs(List arpTable, bool error) + { + ArpTable = arpTable; + Error = error; + } + + /// + /// Constructor for ArpTableEventArgs - assumes no error encountered in retrieving ARP Table + /// + /// The entirety of the retrieved ARP table + public ArpTableEventArgs(List arpTable) + { + ArpTable = arpTable; + Error = false; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs index 39501387..7bf8d5a5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,17 +9,70 @@ namespace PepperDash.Essentials.Core { public static class StringExtensions { + /// + /// Returns null if a string is empty, otherwise returns the string + /// + /// string input + /// null if the string is emtpy, otherwise returns the string public static string NullIfEmpty(this string s) { return string.IsNullOrEmpty(s) ? null : s; } + + /// + /// Returns null if a string is empty or made of only whitespace characters, otherwise returns the string + /// + /// string input + /// null if the string is wempty or made of only whitespace characters, otherwise returns the string public static string NullIfWhiteSpace(this string s) { return string.IsNullOrEmpty(s.Trim()) ? null : s; } + + /// + /// Returns a replacement string if the input string is empty or made of only whitespace characters, otherwise returns the input string + /// + /// input string + /// string to replace with if input string is empty or whitespace + /// returns newString if s is null, emtpy, or made of whitespace characters, otherwise returns s public static string ReplaceIfNullOrEmpty(this string s, string newString) { return string.IsNullOrEmpty(s) ? newString : s; } + + /// + /// Overload for Contains that allows setting an explicit String Comparison + /// + /// Source String + /// String to check in Source String + /// Comparison parameters + /// true of string contains "toCheck" + public static bool Contains(this string source, string toCheck, StringComparison comp) + { + if (string.IsNullOrEmpty(source)) return false; + return source.IndexOf(toCheck, comp) >= 0; + } + + /// + /// Performs TrimStart() and TrimEnd() on source string + /// + /// String to Trim + /// Trimmed String + public static string TrimAll(this string source) + { + return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart().TrimEnd(); + } + + /// + /// Performs TrimStart(chars char[]) and TrimEnd(chars char[]) on source string. + /// + /// String to Trim + /// Char Array to trim from string + /// Trimmed String + public static string TrimAll(this string source, char[] chars) + { + return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart(chars).TrimEnd(chars); + } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 7930f49e..aff99ea7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -200,6 +200,7 @@ + From 97c0bddb48aa4ed3dbdc82cd2fc231c7daa3ae86 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 11 Sep 2023 14:49:46 -0500 Subject: [PATCH 07/40] fix(wip): refactors SetupInputs() and SetupOutputs() to handle io types --- .../Chassis/HdPsXxxController.cs | 192 ++++++++---------- 1 file changed, 80 insertions(+), 112 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index d923949e..9884be8e 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -21,8 +21,6 @@ namespace PepperDash_Essentials_DM.Chassis { private readonly HdPsXxx _chassis; - private readonly HdPs401 _chassis401; - private readonly HdPs621 _chassis621; public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -63,33 +61,35 @@ namespace PepperDash_Essentials_DM.Chassis return; } - InputPorts = new RoutingPortCollection(); + InputPorts = new RoutingPortCollection(); InputNameFeedbacks = new FeedbackCollection(); InputHdcpEnableFeedback = new FeedbackCollection(); - InputNames = new Dictionary(); - //InputNames = props.Inputs; + InputNames = new Dictionary(); OutputPorts = new RoutingPortCollection(); OutputNameFeedbacks = new FeedbackCollection(); OutputRouteNameFeedback = new FeedbackCollection(); OutputNames = new Dictionary(); - //OutputNames = props.Outputs; VideoInputSyncFeedbacks = new FeedbackCollection(); VideoOutputRouteFeedbacks = new FeedbackCollection(); if (_chassis.NumberOfOutputs == 1) { - if (_chassis is HdPs401) - _chassis401 = _chassis as HdPs401; - if (_chassis is HdPs621) - _chassis621 = _chassis as HdPs621; + //if (_chassis is HdPs401) + // _chassis401 = _chassis as HdPs401; + //if (_chassis is HdPs621) + // _chassis621 = _chassis as HdPs621; - AutoRouteFeedback = new BoolFeedback(() => _chassis401.PriorityRouteOnFeedback.BoolValue); + AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); } - SetupInputs(props.Inputs); - SetupOutputs(props.Outputs); + + InputNames = props.Inputs; + SetupInputs(InputNames); + + OutputNames = props.Outputs; + SetupOutputs(OutputNames); AddPostActivationAction(AddFeedbackCollecitons); } @@ -106,35 +106,49 @@ namespace PepperDash_Essentials_DM.Chassis { Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); } - InputNames = dict; - for (uint i = 1; i <= _chassis.NumberOfInputs; i++) + foreach (var item in _chassis.HdmiInputs) { - var index = i; - var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("Input {0}", index) : InputNames[index]; - var input = _chassis.Inputs[index]; - var hdmiInput = _chassis.HdmiInputs[index]; - var dmLiteInput = _chassis.DmLiteInputs[index]; - + var input = item; + var index = item.Number; + var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("HDMI Input {0}", index) : InputNames[index]; + InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); - // TODO [ ] verify which input type is needed - input.Name.StringValue = name; - hdmiInput.Name.StringValue = name; - dmLiteInput.Name.StringValue = name; - var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => hdmiInput.InputPort.HdcpSupportOnFeedback.BoolValue)); + InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); } - _chassis.DMInputChange += _chassis_InputChange; + foreach (var item in _chassis.DmLiteInputs) + { + var input = item; + var index = item.Number; + + var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("DM Input {0}", index) : InputNames[index]; + input.Name.StringValue = name; + + InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); + + var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) + { + FeedbackMatchObject = input + }; + InputPorts.Add(port); + + + InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); + + VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + } + + _chassis.DMInputChange += _chassis_InputChange; } // output setup @@ -149,20 +163,14 @@ namespace PepperDash_Essentials_DM.Chassis { Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); } - OutputNames = dict; - for (uint i = 1; i <= _chassis.NumberOfOutputs; i++) + foreach (var item in _chassis.HdmiDmLiteOutputs) { - var index = i; + var output = item; + var index = item.Number; + var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; - var output = _chassis.Outputs[index]; - var hdmiDmLiteOutput = _chassis.HdmiDmLiteOutputs[index]; - - OutputNameFeedbacks.Add(new StringFeedback(name, () => OutputNames[index])); - - // TODO [ ] verify which output type is needed output.Name.StringValue = name; - hdmiDmLiteOutput.Name.StringValue = name; var port = new RoutingOutputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { @@ -206,10 +214,6 @@ namespace PepperDash_Essentials_DM.Chassis _chassis.OnlineStatusChange += _chassis_OnlineStatusChange; - if (_chassis401 != null) LinkChassis401ToApi(trilist, joinMap); - - if (_chassis621 != null) LinkChassis621ToApi(trilist, joinMap); - LinkChassisInputsToApi(trilist, joinMap); LinkChassisOutputsToApi(trilist, joinMap); @@ -252,36 +256,17 @@ namespace PepperDash_Essentials_DM.Chassis var indexWithOffset = output - 1; trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + indexWithOffset, (a) => - ExecuteNumericSwitch(a, (ushort) output, eRoutingSignalType.AudioVideo)); + ExecuteNumericSwitch(a, (ushort)output, eRoutingSignalType.AudioVideo)); OutputNameFeedbacks[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + indexWithOffset]); OutputRouteNameFeedback[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + indexWithOffset]); VideoOutputRouteFeedbacks[outputName].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + indexWithOffset]); } - } - - - // links HdPs401 chassis to API - private void LinkChassis401ToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) - { - trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis401.AutoRouteOn()); - trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis401.AutoRouteOff()); AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); } - - // links HdPs621 chassis to API - private void LinkChassis621ToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) - { - trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis621.AutoRouteOn()); - trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis621.AutoRouteOff()); - - AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); - } - - #endregion @@ -359,17 +344,9 @@ namespace PepperDash_Essentials_DM.Chassis /// public void EnableAutoRoute() { - if (_chassis.NumberOfInputs != 1) return; + if (_chassis.NumberOfInputs == 1) return; - if (_chassis401 != null) - { - _chassis401.AutoRouteOn(); - } - - if (_chassis621 != null) - { - _chassis621.AutoRouteOn(); - } + _chassis.AutoRouteOn(); } @@ -378,20 +355,12 @@ namespace PepperDash_Essentials_DM.Chassis /// public void DisableAutoRoute() { - if (_chassis.NumberOfInputs != 1) return; + if (_chassis.NumberOfInputs == 1) return; - if (_chassis401 != null) - { - _chassis401.AutoRouteOff(); - } - - if (_chassis621 != null) - { - _chassis621.AutoRouteOff(); - } + _chassis.AutoRouteOff(); } - #region Events + #region Events // _chassis online/offline event @@ -417,31 +386,31 @@ namespace PepperDash_Essentials_DM.Chassis switch (eventId) { case DMInputEventIds.VideoDetectedEventId: - { - Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", eventId); - foreach (var item in VideoInputSyncFeedbacks) { - item.FireUpdate(); + Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", eventId); + foreach (var item in VideoInputSyncFeedbacks) + { + item.FireUpdate(); + } + break; } - break; - } case DMInputEventIds.InputNameFeedbackEventId: case DMInputEventIds.InputNameEventId: case DMInputEventIds.NameFeedbackEventId: - { - Debug.Console(1, this, "Event ID {0}: Updating name feedbacks", eventId); + { + Debug.Console(1, this, "Event ID {0}: Updating name feedbacks", eventId); - var input = args.Number; - var name = _chassis.HdmiInputs[input].NameFeedback.StringValue; + var input = args.Number; + var name = _chassis.HdmiInputs[input].NameFeedback.StringValue; - Debug.Console(1, this, "Input {0} Name {1}", input, name); - break; - } + Debug.Console(1, this, "Input {0} Name {1}", input, name); + break; + } default: - { - Debug.Console(1, this, "Uhandled DM Input Event ID {0}", eventId); - break; - } + { + Debug.Console(1, this, "Uhandled DM Input Event ID {0}", eventId); + break; + } } } @@ -493,7 +462,7 @@ namespace PepperDash_Essentials_DM.Chassis /// - /// Add feedback colleciton arrays to feedback collections + /// Add feedback collection arrays to feedback collections /// /// BoolFeedback[] arrays public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) @@ -587,10 +556,10 @@ namespace PepperDash_Essentials_DM.Chassis /// public void AddFeedbackCollecitons() { - AddFeedbackToList(DeviceNameFeedback); - AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); - AddCollectionsToList(VideoOutputRouteFeedbacks); - AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedback); + //AddFeedbackToList(DeviceNameFeedback); + //AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); + //AddCollectionsToList(VideoOutputRouteFeedbacks); + //AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedback); } @@ -608,7 +577,11 @@ namespace PepperDash_Essentials_DM.Chassis } public override EssentialsDevice BuildDevice(DeviceConfig dc) { - Debug.Console(1, "Factory Attempting to create new HD-PSXxx device"); + var key = dc.Key; + var name = dc.Name; + var type = dc.Type.ToLower(); + + Debug.Console(1, "Factory Attempting to create new {0} device", type); var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); if (props == null) @@ -617,12 +590,7 @@ namespace PepperDash_Essentials_DM.Chassis return null; } - var key = dc.Key; - var name = dc.Name; - var type = dc.Type.ToLower(); - var control = props.Control; - var ipid = control.IpIdInt; - //var address = control.TcpSshProperties.Address; + var ipid = props.Control.IpIdInt; switch (type) { From 08af6370a6124800aacca276b4ec6a56d597e64f Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 11 Sep 2023 15:48:34 -0500 Subject: [PATCH 08/40] fix(wip): adds Debug.Console() statements to identify keys per input; adds ICec interface, pending implementation --- .../Chassis/HdPsXxxController.cs | 164 +++++------------- 1 file changed, 41 insertions(+), 123 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 9884be8e..f4c725f0 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -17,7 +17,7 @@ using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis { [Description("Wrapper class for all HdPsXxx switchers")] - public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, ICec, IHasHdmiInHdcp, IHasFeedback { private readonly HdPsXxx _chassis; @@ -75,15 +75,7 @@ namespace PepperDash_Essentials_DM.Chassis VideoOutputRouteFeedbacks = new FeedbackCollection(); if (_chassis.NumberOfOutputs == 1) - { - //if (_chassis is HdPs401) - // _chassis401 = _chassis as HdPs401; - //if (_chassis is HdPs621) - // _chassis621 = _chassis as HdPs621; - AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); - } - InputNames = props.Inputs; SetupInputs(InputNames); @@ -91,7 +83,7 @@ namespace PepperDash_Essentials_DM.Chassis OutputNames = props.Outputs; SetupOutputs(OutputNames); - AddPostActivationAction(AddFeedbackCollecitons); + //AddPostActivationAction(); } // input setup @@ -107,6 +99,20 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); } + // TODO [ ] testing + var hdmiKeys = _chassis.HdmiInputs.Keys; + foreach (var key in hdmiKeys) + { + Debug.Console(0, this, "HDMI Input key-'{0}'", key); + } + + var dmKeys = _chassis.DmLiteInputs.Keys; + foreach (var key in dmKeys) + { + Debug.Console(0, this, "DM Input key-'{0}'", key); + } + + foreach (var item in _chassis.HdmiInputs) { var input = item; @@ -123,7 +129,7 @@ namespace PepperDash_Essentials_DM.Chassis InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); } foreach (var item in _chassis.DmLiteInputs) @@ -164,9 +170,17 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); } + + // TODO [ ] testing + var keys = _chassis.HdmiDmLiteOutputs.Keys; + foreach (var key in keys) + { + Debug.Console(0, this, "HdmiDmLite Output key-'{0}'", key); + } + foreach (var item in _chassis.HdmiDmLiteOutputs) { - var output = item; + var output = item; var index = item.Number; var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; @@ -182,7 +196,7 @@ namespace PepperDash_Essentials_DM.Chassis VideoOutputRouteFeedbacks.Add(new IntFeedback(name, () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); } - + _chassis.DMOutputChange += _chassis_OutputChange; } @@ -268,7 +282,7 @@ namespace PepperDash_Essentials_DM.Chassis } #endregion - + /// /// Executes a device switch using objects @@ -455,115 +469,7 @@ namespace PepperDash_Essentials_DM.Chassis } - #endregion - - - #region FeedbacksAndFeedbackCollections - - - /// - /// Add feedback collection arrays to feedback collections - /// - /// BoolFeedback[] arrays - public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) - { - foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) - { - AddCollectionsToList(item); - } - } - - - /// - /// Add feedback colleciton arrays to feedback collections - /// - /// IntFeedback[] arrays - public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) - { - foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) - { - AddCollectionsToList(item); - } - } - - - /// - /// Add feedback colleciton arrays to feedback collections - /// - /// StringFeedback[] arrays - public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) - { - foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) - { - AddCollectionsToList(item); - } - } - - - /// - /// Adds feedback colleciton to feedback collections - /// - /// BoolFeedback - public void AddCollectionToList(FeedbackCollection feedbackCollection) - { - foreach (var item in feedbackCollection.Where(item => item != null)) - { - AddFeedbackToList(item); - } - } - - - /// - /// Adds feedback colleciton to feedback collections - /// - /// IntFeedback - public void AddCollectionToList(FeedbackCollection feedbackCollection) - { - foreach (var item in feedbackCollection.Where(item => item != null)) - { - AddFeedbackToList(item); - } - } - - - /// - /// Adds feedback colleciton to feedback collections - /// - /// StringFeedback - public void AddCollectionToList(FeedbackCollection feedbackCollection) - { - foreach (var item in feedbackCollection.Where(item => item != null)) - { - AddFeedbackToList(item); - } - } - - - /// - /// Adds individual feedbacks to feedback collection - /// - /// Feedback - public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback fb) - { - if (fb == null || Feedbacks.Contains(fb)) return; - - Feedbacks.Add(fb); - } - - - /// - /// Adds provided feedbacks to feedback collection list - /// - public void AddFeedbackCollecitons() - { - //AddFeedbackToList(DeviceNameFeedback); - //AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); - //AddCollectionsToList(VideoOutputRouteFeedbacks); - //AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedback); - } - - - #endregion + #endregion #region Factory @@ -621,5 +527,17 @@ namespace PepperDash_Essentials_DM.Chassis #endregion + + // TODO [ ] Implement CEC control + // return _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec; + public Cec StreamCec { get; private set; } + + public IntFeedback HdmiInHdcpStateFeedback { get; private set; } + public void SetHdmiInHdcpState(eHdcpCapabilityType hdcpState) + { + throw new NotImplementedException(); + } + + public eHdcpCapabilityType HdmiInHdcpCapability { get; private set; } } } \ No newline at end of file From 4e33743f5015742798a556096b61d47905a777eb Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 11 Sep 2023 19:24:21 -0500 Subject: [PATCH 09/40] refactor: SetupInput() and SetupOutput() methods to set standard keys for ports that are instantiated --- .../Chassis/HdPsXxxController.cs | 56 ++++++++----------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index f4c725f0..8bfab826 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM; @@ -19,7 +17,6 @@ namespace PepperDash_Essentials_DM.Chassis [Description("Wrapper class for all HdPsXxx switchers")] public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, ICec, IHasHdmiInHdcp, IHasFeedback { - private readonly HdPsXxx _chassis; public RoutingPortCollection InputPorts { get; private set; } @@ -99,32 +96,20 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); } - // TODO [ ] testing - var hdmiKeys = _chassis.HdmiInputs.Keys; - foreach (var key in hdmiKeys) - { - Debug.Console(0, this, "HDMI Input key-'{0}'", key); - } - - var dmKeys = _chassis.DmLiteInputs.Keys; - foreach (var key in dmKeys) - { - Debug.Console(0, this, "DM Input key-'{0}'", key); - } - - foreach (var item in _chassis.HdmiInputs) { var input = item; var index = item.Number; + var key = string.Format("hdmiIn{0}", index); var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("HDMI Input {0}", index) : InputNames[index]; InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); - var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) + var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; + Debug.Console(1, this, "Adding HDMI Input port: {0}", port.Key); InputPorts.Add(port); InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); @@ -136,7 +121,7 @@ namespace PepperDash_Essentials_DM.Chassis { var input = item; var index = item.Number; - + var key = string.Format("dmLiteIn{0}", index); var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("DM Input {0}", index) : InputNames[index]; input.Name.StringValue = name; @@ -146,8 +131,8 @@ namespace PepperDash_Essentials_DM.Chassis { FeedbackMatchObject = input }; + Debug.Console(0, this, "Adding DM Input port: {0}",port.Key); InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); @@ -170,26 +155,22 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); } - - // TODO [ ] testing - var keys = _chassis.HdmiDmLiteOutputs.Keys; - foreach (var key in keys) - { - Debug.Console(0, this, "HdmiDmLite Output key-'{0}'", key); - } - foreach (var item in _chassis.HdmiDmLiteOutputs) { - var output = item; + var output = item; var index = item.Number; - + var key = string.Format("hdmiDmLiteOut{0}", index); var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; output.Name.StringValue = name; - var port = new RoutingOutputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) + var port = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { - FeedbackMatchObject = output + FeedbackMatchObject = output, + // set port for CEC + Port = output }; + Debug.Console(0, this, "Adding HdmiDmLite Output port: {0} {1}", + port.Key, port.ParentDevice); OutputPorts.Add(port); OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); @@ -530,7 +511,16 @@ namespace PepperDash_Essentials_DM.Chassis // TODO [ ] Implement CEC control // return _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec; - public Cec StreamCec { get; private set; } + public Cec StreamCec + { + get + { + return _chassis.NumberOfOutputs == 1 + //? _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec + ? _chassis.HdmiDmLiteOutputs[0].HdmiOutput.HdmiOutputPort.StreamCec + : null; + } + } public IntFeedback HdmiInHdcpStateFeedback { get; private set; } public void SetHdmiInHdcpState(eHdcpCapabilityType hdcpState) From 27bac4e83dfd83fdc46a861c1f113f072e73e76e Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 10:09:37 -0500 Subject: [PATCH 10/40] fix(wip): updates stream cec implementation to handle switchers with multiple outputs --- .../Chassis/HdPsXxxController.cs | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 8bfab826..c7ef719c 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -15,7 +15,7 @@ using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis { [Description("Wrapper class for all HdPsXxx switchers")] - public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, ICec, IHasHdmiInHdcp, IHasFeedback + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback { private readonly HdPsXxx _chassis; @@ -61,7 +61,7 @@ namespace PepperDash_Essentials_DM.Chassis InputPorts = new RoutingPortCollection(); InputNameFeedbacks = new FeedbackCollection(); InputHdcpEnableFeedback = new FeedbackCollection(); - InputNames = new Dictionary(); + InputNames = new Dictionary(); OutputPorts = new RoutingPortCollection(); OutputNameFeedbacks = new FeedbackCollection(); @@ -79,8 +79,6 @@ namespace PepperDash_Essentials_DM.Chassis OutputNames = props.Outputs; SetupOutputs(OutputNames); - - //AddPostActivationAction(); } // input setup @@ -102,19 +100,19 @@ namespace PepperDash_Essentials_DM.Chassis var index = item.Number; var key = string.Format("hdmiIn{0}", index); var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("HDMI Input {0}", index) : InputNames[index]; - + InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; - Debug.Console(1, this, "Adding HDMI Input port: {0}", port.Key); + Debug.Console(1, this, "Adding Input port: {0}", port.Key); InputPorts.Add(port); InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); } foreach (var item in _chassis.DmLiteInputs) @@ -127,13 +125,13 @@ namespace PepperDash_Essentials_DM.Chassis InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); - var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) + var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; - Debug.Console(0, this, "Adding DM Input port: {0}",port.Key); + Debug.Console(0, this, "Adding Input port: {0}", port.Key); InputPorts.Add(port); - + InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); @@ -169,15 +167,35 @@ namespace PepperDash_Essentials_DM.Chassis // set port for CEC Port = output }; - Debug.Console(0, this, "Adding HdmiDmLite Output port: {0} {1}", - port.Key, port.ParentDevice); + Debug.Console(0, this, "Adding Output port: {0}", port.Key); OutputPorts.Add(port); OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); VideoOutputRouteFeedbacks.Add(new IntFeedback(name, () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); + + // TODO [ ] Investigate setting input priorities per output + // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} + // default priority level input 1-4 ascending + output.OutputPort.InputPriorities(new byte[] { 1, 2, 3, 4 }); + + if (port.Port == null) continue; + + var hdmiOutputStreamCec = output.HdmiOutput.HdmiOutputPort.StreamCec; + if (hdmiOutputStreamCec != null) + { + var streamCec = new StreamCecWrapper(string.Format("{0}-hdmiOut{1}-streamCec", Key, index), hdmiOutputStreamCec); + DeviceManager.AddDevice(streamCec); + } + + var dmLiteOutputStreamCec = output.DmLiteOutput.DmLiteOutputPort.StreamCec; + if (dmLiteOutputStreamCec != null) + { + var streamCec = new StreamCecWrapper(string.Format("{0}-dmLiteOut{1}-streamCec", Key, index), dmLiteOutputStreamCec); + DeviceManager.AddDevice(streamCec); + } } - + _chassis.DMOutputChange += _chassis_OutputChange; } @@ -263,7 +281,7 @@ namespace PepperDash_Essentials_DM.Chassis } #endregion - + /// /// Executes a device switch using objects @@ -450,7 +468,7 @@ namespace PepperDash_Essentials_DM.Chassis } - #endregion + #endregion #region Factory @@ -508,26 +526,18 @@ namespace PepperDash_Essentials_DM.Chassis #endregion + } - // TODO [ ] Implement CEC control - // return _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec; - public Cec StreamCec + + public class StreamCecWrapper : IKeyed, ICec + { + public string Key { get; private set; } + public Cec StreamCec { get; private set; } + + public StreamCecWrapper(string key, Cec streamCec) { - get - { - return _chassis.NumberOfOutputs == 1 - //? _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec - ? _chassis.HdmiDmLiteOutputs[0].HdmiOutput.HdmiOutputPort.StreamCec - : null; - } + Key = key; + StreamCec = streamCec; } - - public IntFeedback HdmiInHdcpStateFeedback { get; private set; } - public void SetHdmiInHdcpState(eHdcpCapabilityType hdcpState) - { - throw new NotImplementedException(); - } - - public eHdcpCapabilityType HdmiInHdcpCapability { get; private set; } } } \ No newline at end of file From 1aa95905872d5007f11ed7c55ba33184c30fa63c Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 13:23:18 -0500 Subject: [PATCH 11/40] feature: adds DmInputChange event --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index c7ef719c..1c6f8781 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -38,6 +38,7 @@ namespace PepperDash_Essentials_DM.Chassis public BoolFeedback AutoRouteFeedback { get; private set; } public event EventHandler NumericSwitchChange; + public event EventHandler DmInputChange; /// /// Constructor @@ -425,6 +426,8 @@ namespace PepperDash_Essentials_DM.Chassis break; } } + + OnDmInputChange(args); } @@ -457,16 +460,20 @@ namespace PepperDash_Essentials_DM.Chassis } - /// - /// Raise an event when the status of a switch object changes. - /// - /// Argumetns defined as IKeyName sender, output, input, & eRoutingSignalType + // Raise an event when the status of a switch object changes. private void OnSwitchChange(RoutingNumericEventArgs args) { var newEvent = NumericSwitchChange; if (newEvent != null) newEvent(this, args); } + // Raise an event when the DM input changes. + private void OnDmInputChange(DMInputEventArgs args) + { + var newEvent = DmInputChange; + if (newEvent != null) newEvent(this, args); + } + #endregion From da5d2d74f29d7be3a02f9147399fe8fb3420f4f8 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 14:36:17 -0500 Subject: [PATCH 12/40] fix: removes OutputPort.InputPriorities reference --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 1c6f8781..7c1e0431 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -10,6 +10,7 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash_Essentials_Core.Bridges; +using PepperDash_Essentials_DM; using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis @@ -173,12 +174,14 @@ namespace PepperDash_Essentials_DM.Chassis OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); - VideoOutputRouteFeedbacks.Add(new IntFeedback(name, () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); + VideoOutputRouteFeedbacks.Add(new IntFeedback(name, + () => output.VideoOutFeedback == null ? 0 : (int) output.VideoOutFeedback.Number)); // TODO [ ] Investigate setting input priorities per output // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} - // default priority level input 1-4 ascending - output.OutputPort.InputPriorities(new byte[] { 1, 2, 3, 4 }); + // default priority level input 1-4 ascending + //var priorities = new byte[] {1,2,3,4}; + //output.OutputPort.InputPriorities(priorities); if (port.Port == null) continue; From 189c4706030e4d5cf8c1de496aee94130ef00b02 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 17:10:25 -0500 Subject: [PATCH 13/40] feature(wip): adds inputPriorities configuration property --- .../Chassis/HdPsXxxController.cs | 22 ++++++++++++++----- .../Config/HdPsXxxPropertiesConfig.cs | 12 +++++----- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 7c1e0431..2e998133 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -10,7 +10,6 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash_Essentials_Core.Bridges; -using PepperDash_Essentials_DM; using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis @@ -19,6 +18,7 @@ namespace PepperDash_Essentials_DM.Chassis public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback { private readonly HdPsXxx _chassis; + private byte[] _inputPriorityParams; public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -76,6 +76,12 @@ namespace PepperDash_Essentials_DM.Chassis if (_chassis.NumberOfOutputs == 1) AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); + if (props.InputPriorities != null) + { + _inputPriorityParams = new byte[_chassis.NumberOfInputs]; + _inputPriorityParams = GetInputPriorities(props); + } + InputNames = props.Inputs; SetupInputs(InputNames); @@ -83,6 +89,12 @@ namespace PepperDash_Essentials_DM.Chassis SetupOutputs(OutputNames); } + // get input priorities + private byte[] GetInputPriorities(HdPsXxxPropertiesConfig props) + { + throw new NotImplementedException(); + } + // input setup private void SetupInputs(Dictionary dict) { @@ -175,13 +187,13 @@ namespace PepperDash_Essentials_DM.Chassis OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); VideoOutputRouteFeedbacks.Add(new IntFeedback(name, - () => output.VideoOutFeedback == null ? 0 : (int) output.VideoOutFeedback.Number)); + () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); // TODO [ ] Investigate setting input priorities per output // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} - // default priority level input 1-4 ascending - //var priorities = new byte[] {1,2,3,4}; - //output.OutputPort.InputPriorities(priorities); + // default priority level input 1-4 ascending + if (_inputPriorityParams != null && _inputPriorityParams.Count() > 0) + output.OutputPort.InputPriorities(_inputPriorityParams); if (port.Port == null) continue; diff --git a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs index c02fc511..576b74f0 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using Newtonsoft.Json; using PepperDash.Core; -using PepperDash.Essentials.DM.Config; namespace PepperDash_Essentials_DM.Config { @@ -11,18 +10,17 @@ namespace PepperDash_Essentials_DM.Config public ControlPropertiesConfig Control { get; set; } [JsonProperty("inputs")] - //public Dictionary Inputs { get; set; } public Dictionary Inputs { get; set; } - + [JsonProperty("outputs")] - //public Dictionary Outputs { get; set; } public Dictionary Outputs { get; set; } + // "inputPriorities": "1,4,3,2" + [JsonProperty("inputPriorities")] + public string InputPriorities { get; set; } + public HdPsXxxPropertiesConfig() { - //Inputs = new Dictionary(); - //Outputs = new Dictionary(); - Inputs = new Dictionary(); Outputs = new Dictionary(); } From e590c7cedb251cf4b324b4e4a43bd49afaf0c85b Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 19:26:55 -0500 Subject: [PATCH 14/40] feature(wip): adds inputPriorities configuration property --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 2e998133..bba85d25 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -18,7 +18,7 @@ namespace PepperDash_Essentials_DM.Chassis public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback { private readonly HdPsXxx _chassis; - private byte[] _inputPriorityParams; + //private byte[] _inputPriorityParams; public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -76,11 +76,11 @@ namespace PepperDash_Essentials_DM.Chassis if (_chassis.NumberOfOutputs == 1) AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); - if (props.InputPriorities != null) - { - _inputPriorityParams = new byte[_chassis.NumberOfInputs]; - _inputPriorityParams = GetInputPriorities(props); - } + //if (props.InputPriorities != null) + //{ + // _inputPriorityParams = new byte[_chassis.NumberOfInputs]; + // _inputPriorityParams = GetInputPriorities(props); + //} InputNames = props.Inputs; SetupInputs(InputNames); @@ -192,8 +192,8 @@ namespace PepperDash_Essentials_DM.Chassis // TODO [ ] Investigate setting input priorities per output // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} // default priority level input 1-4 ascending - if (_inputPriorityParams != null && _inputPriorityParams.Count() > 0) - output.OutputPort.InputPriorities(_inputPriorityParams); + //if (_inputPriorityParams != null && _inputPriorityParams.Count() > 0) + // output.OutputPort.InputPriorities(_inputPriorityParams); if (port.Port == null) continue; From 334a62c32943d80337f9a382fe934a4af337662b Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 08:32:07 -0500 Subject: [PATCH 15/40] fix: wraps GetDeviceForKey and GetFeedbackProperty methods in a try/catch --- .../Touchpanels/Mpc3Touchpanel.cs | 73 ++++++++++++------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index f4611a70..f1153879 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Globalization; using Crestron.SimplSharpPro; using Newtonsoft.Json; @@ -27,6 +28,7 @@ namespace PepperDash.Essentials.Core.Touchpanels } _touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange; + _buttons = buttons; if (_buttons == null) { @@ -55,6 +57,8 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void InitializeButton(string key, KeypadButton config) { + Debug.Console(1, this, "Initializing button '{0}'...", key); + if (config == null) { Debug.Console(1, this, "Button '{0}' config is null, unable to initialize", key); @@ -131,6 +135,8 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void InitializeButtonFeedback(string key, KeypadButton config) { + Debug.Console(1, this, "Initializing button '{0}' feedback...", key); + if (config == null) { Debug.Console(1, this, "Button '{0}' config is null, unable to initialize feedback", key); @@ -144,37 +150,54 @@ namespace PepperDash.Essentials.Core.Touchpanels var buttonFeedback = config.Feedback; if (buttonFeedback == null) { - Debug.Console(1, this, "Button '{0}' feedback not configured and will not be implemented. Verify feedback is configured if required.", key); + Debug.Console(1, this, "Button '{0}' feedback not configured and will not be implemented. If feedback is required, verify configuration.", + key); return; } - var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; - if (device == null) + Feedback deviceFeedback = null; + + try { - Debug.Console(1, this, "Button '{0}' feedback device with key '{0}' not found, feedback will not be implemented. Verify feedback deviceKey is properly configured.", - buttonFeedback.DeviceKey); + var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; + if (device == null) + { + Debug.Console(1, this, "Button '{0}' feedback with deviceKey '{1}' not found, feedback will not be implemented. Verify feedback deviceKey is properly configured.", + key, buttonFeedback.DeviceKey); + return; + } + + // TODO [ ] verify if this can replace the current method + deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + //Debug.Console(0, this, "deviceFeedback.GetType().Name: '{0}'", deviceFeedback.GetType().Name); + //switch (feedback.GetType().Name.ToLower()) + //{ + // case("boolfeedback"): + // { + // break; + // } + // case("intfeedback"): + // { + // break; + // } + // case("stringfeedback"): + // { + // break; + // } + //} + } + catch (Exception ex) + { + Debug.Console(0, this, "Failed to initialize button '{0}' feedback with deviceKey '{1}'. If feedback is required, verify configuration.", + key, buttonFeedback.DeviceKey); + + Debug.Console(1, this, "InitializeButtonFeedback Exception Message: {0}", ex.Message); + Debug.Console(2, this, "InitializeButtonFeedback Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) Debug.Console(2, this, "InitializeButtonFeedback Exception InnerExceptioni: {0}", ex.InnerException); + return; } - // TODO [ ] verify if this can replace the current method - var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); - Debug.Console(0, this, "deviceFeedback.GetType().Name: '{0}'", deviceFeedback.GetType().Name); - //switch (feedback.GetType().Name.ToLower()) - //{ - // case("boolfeedback"): - // { - // break; - // } - // case("intfeedback"): - // { - // break; - // } - // case("stringfeedback"): - // { - // break; - // } - //} - var boolFeedback = deviceFeedback as BoolFeedback; var intFeedback = deviceFeedback as IntFeedback; From 0fad667fabfc1fc5f1776cd6891c228254ed38e0 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 08:56:13 -0500 Subject: [PATCH 16/40] fix: adds additional debug statements when attempting to get feedback property for device --- .../Touchpanels/Mpc3Touchpanel.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index f1153879..296965f9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -155,7 +155,7 @@ namespace PepperDash.Essentials.Core.Touchpanels return; } - Feedback deviceFeedback = null; + Feedback deviceFeedback; try { @@ -166,9 +166,16 @@ namespace PepperDash.Essentials.Core.Touchpanels key, buttonFeedback.DeviceKey); return; } + + deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + if (deviceFeedback == null) + { + Debug.Console(1, this, "Button '{0}' feedback failed to get feedback property for '{1}', feedback will not be implemented. Verify feedback deviceKey is properly configured.", + key, buttonFeedback.FeedbackName); + return; + } // TODO [ ] verify if this can replace the current method - deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); //Debug.Console(0, this, "deviceFeedback.GetType().Name: '{0}'", deviceFeedback.GetType().Name); //switch (feedback.GetType().Name.ToLower()) //{ From 5a67a4060db2c715081f05cbb428218b919c9c76 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 09:31:25 -0500 Subject: [PATCH 17/40] feat: adds routing sync provider interface and delegate --- .../PepperDashEssentialsBase/Routing/RoutingInterfaces.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs index 467bf045..e24480ff 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs @@ -204,4 +204,11 @@ namespace PepperDash.Essentials.Core SigType = sigType; } } + + public interface IRoutingSyncProvider + { + event RoutingSyncProviderDelegate SyncChanged; + } + + public delegate void RoutingSyncProviderDelegate(uint inputNumber, bool hasSync); } \ No newline at end of file From 8b6a9db7e0a04aac3868e8b31d4883f52de7dc6c Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 09:32:44 -0500 Subject: [PATCH 18/40] refactor: refactors GetCecPort method --- .../Comm and IR/CommFactory.cs | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs index 9667b5b9..fd5fcfe2 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs @@ -117,39 +117,37 @@ namespace PepperDash.Essentials.Core { var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); - if (dev != null) - { - if (!String.IsNullOrEmpty(config.ControlPortName)) - { + Debug.Console(0, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null + ? "is not valid, failed to create build cec port" + : "found in device manager, attempting to build cec port"); - var inputPort = (dev as IRoutingInputsOutputs).InputPorts[config.ControlPortName]; + if (dev == null) + return null; - if (inputPort != null) - { - if (inputPort.Port is ICec) - return inputPort.Port as ICec; - } + if (String.IsNullOrEmpty(config.ControlPortName)) + { + Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); + return null; + } - var outputPort = (dev as IRoutingInputsOutputs).OutputPorts[config.ControlPortName]; + var inputPort = (dev as IRoutingInputsOutputs).InputPorts[config.ControlPortName]; + if (inputPort != null) + { + if (inputPort.Port is ICec) + return inputPort.Port as ICec; + } - if (outputPort != null) - { - if (outputPort.Port is ICec) - return outputPort.Port as ICec; - } + var outputPort = (dev as IRoutingInputsOutputs).OutputPorts[config.ControlPortName]; + if (outputPort != null) + { + if (outputPort.Port is ICec) + return outputPort.Port as ICec; + } - else - Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called: '{1}'", - config.ControlPortDevKey, config.ControlPortName); - } - else - { - Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); - } - } - Debug.Console(0, "GetCecPort: Device '{0}' is not a valid device.", config.ControlPortDevKey); + Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called: '{1}'", + config.ControlPortDevKey, config.ControlPortName); - return null; + return null; } /// From 9fb16f30b06ec392aa7194dbbacd2a7177c8520a Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 10:02:20 -0500 Subject: [PATCH 19/40] refactor: Changes IRoutingHasSync interface - Changed IRoutingHasSync interface to IRoutingHasVideoInputSyncFeedbacks. - Remvoed IRoutingHasSynDelegate - Added interface to HdPsXxxController class --- .../PepperDashEssentialsBase/Routing/RoutingInterfaces.cs | 8 +++----- .../Essentials_DM/Chassis/HdPsXxxController.cs | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs index e24480ff..45245066 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs @@ -205,10 +205,8 @@ namespace PepperDash.Essentials.Core } } - public interface IRoutingSyncProvider + public interface IRoutingHasVideoInputSyncFeedbacks { - event RoutingSyncProviderDelegate SyncChanged; - } - - public delegate void RoutingSyncProviderDelegate(uint inputNumber, bool hasSync); + FeedbackCollection VideoInputSyncFeedbacks { get; } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index bba85d25..1bf40083 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -15,7 +15,7 @@ using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis { [Description("Wrapper class for all HdPsXxx switchers")] - public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IRoutingHasVideoInputSyncFeedbacks { private readonly HdPsXxx _chassis; //private byte[] _inputPriorityParams; From 393033b6c9c4a80778e2c68c3921f97bc592db9d Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 10:13:39 -0500 Subject: [PATCH 20/40] refactor: Updates HdPsXxxController class - Modifies `SetupInput()` and `SetupOutput()` - Renames `GetInputPriorities()` to `SetInputPriorities()` --- .../Chassis/HdPsXxxController.cs | 106 ++++++++---------- 1 file changed, 46 insertions(+), 60 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 1bf40083..705061d2 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; @@ -18,7 +19,6 @@ namespace PepperDash_Essentials_DM.Chassis public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IRoutingHasVideoInputSyncFeedbacks { private readonly HdPsXxx _chassis; - //private byte[] _inputPriorityParams; public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -41,6 +41,7 @@ namespace PepperDash_Essentials_DM.Chassis public event EventHandler NumericSwitchChange; public event EventHandler DmInputChange; + /// /// Constructor /// @@ -76,12 +77,6 @@ namespace PepperDash_Essentials_DM.Chassis if (_chassis.NumberOfOutputs == 1) AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); - //if (props.InputPriorities != null) - //{ - // _inputPriorityParams = new byte[_chassis.NumberOfInputs]; - // _inputPriorityParams = GetInputPriorities(props); - //} - InputNames = props.Inputs; SetupInputs(InputNames); @@ -90,7 +85,7 @@ namespace PepperDash_Essentials_DM.Chassis } // get input priorities - private byte[] GetInputPriorities(HdPsXxxPropertiesConfig props) + private byte[] SetInputPriorities(HdPsXxxPropertiesConfig props) { throw new NotImplementedException(); } @@ -103,52 +98,59 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "Failed to setup inputs, properties are null"); return; } - foreach (var kvp in dict) - { - Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); - } - + + // iterate through HDMI inputs foreach (var item in _chassis.HdmiInputs) { var input = item; var index = item.Number; var key = string.Format("hdmiIn{0}", index); - var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("HDMI Input {0}", index) : InputNames[index]; + input.Name.StringValue = string.IsNullOrEmpty(InputNames[index]) + ? string.Format("HDMI Input {0}", index) + : InputNames[index]; - InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => InputNames[index])); var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; - Debug.Console(1, this, "Adding Input port: {0}", port.Key); + Debug.Console(1, this, "Adding Input port: {0} - {1}", port.Key, input.Name); InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); + InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.VideoDetectedFeedback.BoolValue)); } + // iterate through DM Lite inputs foreach (var item in _chassis.DmLiteInputs) { var input = item; var index = item.Number; var key = string.Format("dmLiteIn{0}", index); - var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("DM Input {0}", index) : InputNames[index]; - input.Name.StringValue = name; + input.Name.StringValue = string.IsNullOrEmpty(InputNames[index]) + ? string.Format("DM Input {0}", index) + : InputNames[index]; - InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => InputNames[index])); var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; - Debug.Console(0, this, "Adding Input port: {0}", port.Key); + Debug.Console(0, this, "Adding Input port: {0} - {1}", port.Key, input.Name); InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); + InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.VideoDetectedFeedback.BoolValue)); } _chassis.DMInputChange += _chassis_InputChange; @@ -162,54 +164,38 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "Failed to setup outputs, properties are null"); return; } - foreach (var kvp in dict) - { - Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); - } foreach (var item in _chassis.HdmiDmLiteOutputs) { var output = item; var index = item.Number; var key = string.Format("hdmiDmLiteOut{0}", index); - var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; - output.Name.StringValue = name; + + output.Name.StringValue = string.IsNullOrEmpty(OutputNames[index]) + ? string.Format("Output {0}", index) + : OutputNames[index]; - var port = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) + var hdmiPort = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { FeedbackMatchObject = output, - // set port for CEC - Port = output + Port = output.HdmiOutput.HdmiOutputPort.StreamCec }; - Debug.Console(0, this, "Adding Output port: {0}", port.Key); - OutputPorts.Add(port); + Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, output.Name); + OutputPorts.Add(hdmiPort); - OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); + var dmLitePort = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, output, this) + { + FeedbackMatchObject = output, + Port = output.DmLiteOutput.DmLiteOutputPort.StreamCec + }; + Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, output.Name); + OutputPorts.Add(dmLitePort); - VideoOutputRouteFeedbacks.Add(new IntFeedback(name, + OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => output.VideoOutFeedback.NameFeedback.StringValue)); + + VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); - - // TODO [ ] Investigate setting input priorities per output - // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} - // default priority level input 1-4 ascending - //if (_inputPriorityParams != null && _inputPriorityParams.Count() > 0) - // output.OutputPort.InputPriorities(_inputPriorityParams); - - if (port.Port == null) continue; - - var hdmiOutputStreamCec = output.HdmiOutput.HdmiOutputPort.StreamCec; - if (hdmiOutputStreamCec != null) - { - var streamCec = new StreamCecWrapper(string.Format("{0}-hdmiOut{1}-streamCec", Key, index), hdmiOutputStreamCec); - DeviceManager.AddDevice(streamCec); - } - - var dmLiteOutputStreamCec = output.DmLiteOutput.DmLiteOutputPort.StreamCec; - if (dmLiteOutputStreamCec != null) - { - var streamCec = new StreamCecWrapper(string.Format("{0}-dmLiteOut{1}-streamCec", Key, index), dmLiteOutputStreamCec); - DeviceManager.AddDevice(streamCec); - } } _chassis.DMOutputChange += _chassis_OutputChange; @@ -547,7 +533,7 @@ namespace PepperDash_Essentials_DM.Chassis } - #endregion + #endregion } From 7ecb2ecf6dfeadcf2191d49cca1be0a03e10b54d Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 16:43:23 -0500 Subject: [PATCH 21/40] fix: updates SetupOutputs to create a hdmiOutX and dmLiteOutX port --- .../Chassis/HdPsXxxController.cs | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 705061d2..cbcf2a7c 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -105,10 +105,12 @@ namespace PepperDash_Essentials_DM.Chassis var input = item; var index = item.Number; var key = string.Format("hdmiIn{0}", index); - input.Name.StringValue = string.IsNullOrEmpty(InputNames[index]) - ? string.Format("HDMI Input {0}", index) + var name = string.IsNullOrEmpty(InputNames[index]) + ? string.Format("HDMI Input {0}", index) : InputNames[index]; + input.Name.StringValue = name; + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), () => InputNames[index])); @@ -116,7 +118,7 @@ namespace PepperDash_Essentials_DM.Chassis { FeedbackMatchObject = input }; - Debug.Console(1, this, "Adding Input port: {0} - {1}", port.Key, input.Name); + Debug.Console(1, this, "Adding Input port: {0} - {1}", port.Key, name); InputPorts.Add(port); InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), @@ -132,10 +134,12 @@ namespace PepperDash_Essentials_DM.Chassis var input = item; var index = item.Number; var key = string.Format("dmLiteIn{0}", index); - input.Name.StringValue = string.IsNullOrEmpty(InputNames[index]) + var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("DM Input {0}", index) : InputNames[index]; + input.Name.StringValue = name; + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), () => InputNames[index])); @@ -143,7 +147,7 @@ namespace PepperDash_Essentials_DM.Chassis { FeedbackMatchObject = input }; - Debug.Console(0, this, "Adding Input port: {0} - {1}", port.Key, input.Name); + Debug.Console(0, this, "Adding Input port: {0} - {1}", port.Key, name); InputPorts.Add(port); InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), @@ -169,26 +173,28 @@ namespace PepperDash_Essentials_DM.Chassis { var output = item; var index = item.Number; - var key = string.Format("hdmiDmLiteOut{0}", index); - - output.Name.StringValue = string.IsNullOrEmpty(OutputNames[index]) + var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) - : OutputNames[index]; + : OutputNames[index]; + + output.Name.StringValue = name; - var hdmiPort = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) + var hdmiKey = string.Format("hdmiOut{0}", index); + var hdmiPort = new RoutingOutputPort(hdmiKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { FeedbackMatchObject = output, Port = output.HdmiOutput.HdmiOutputPort.StreamCec }; - Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, output.Name); + Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, name); OutputPorts.Add(hdmiPort); - var dmLitePort = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, output, this) + var dmLiteKey = string.Format("dmLiteOut{0}", index); + var dmLitePort = new RoutingOutputPort(dmLiteKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, output, this) { FeedbackMatchObject = output, Port = output.DmLiteOutput.DmLiteOutputPort.StreamCec }; - Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, output.Name); + Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, name); OutputPorts.Add(dmLitePort); OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), From 6d020132cfb2283fbcd1fa3bee89f3f4081eedac Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 20 Sep 2023 15:38:25 -0500 Subject: [PATCH 22/40] refactor: GetCecPort method to handle exceptions --- .../Comm and IR/CommFactory.cs | 71 +++++++++++-------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs index fd5fcfe2..549404e0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs @@ -115,39 +115,54 @@ namespace PepperDash.Essentials.Core /// public static ICec GetCecPort(ControlPropertiesConfig config) { - var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); - - Debug.Console(0, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null - ? "is not valid, failed to create build cec port" - : "found in device manager, attempting to build cec port"); - - if (dev == null) - return null; - - if (String.IsNullOrEmpty(config.ControlPortName)) + try { - Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); - return null; + var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); + + Debug.Console(0, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null + ? "is not valid, failed to get cec port" + : "found in device manager, attempting to get cec port"); + + if (dev == null) + return null; + + if (String.IsNullOrEmpty(config.ControlPortName)) + { + Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); + return null; + } + + + var inputsOutputs = dev as IRoutingInputsOutputs; + if (inputsOutputs == null) + { + Debug.Console(0, "GetCecPort: Device '{0}' does not support IRoutingInputsOutputs, failed to get CEC port called '{1}'", + config.ControlPortDevKey, config.ControlPortName); + + return null; + } + + var inputPort = inputsOutputs.InputPorts[config.ControlPortName]; + if (inputPort != null && inputPort.Port is ICec) + return inputPort.Port as ICec; + + + var outputPort = inputsOutputs.OutputPorts[config.ControlPortName]; + if (outputPort != null && outputPort.Port is ICec) + return outputPort.Port as ICec; + } + catch (Exception ex) + { + Debug.Console(1, "GetCecPort Exception Message: {0}", ex.Message); + Debug.Console(2, "GetCecPort Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) + Debug.Console(0, "GetCecPort Exception InnerException: {0}", ex.InnerException); } - var inputPort = (dev as IRoutingInputsOutputs).InputPorts[config.ControlPortName]; - if (inputPort != null) - { - if (inputPort.Port is ICec) - return inputPort.Port as ICec; - } - - var outputPort = (dev as IRoutingInputsOutputs).OutputPorts[config.ControlPortName]; - if (outputPort != null) - { - if (outputPort.Port is ICec) - return outputPort.Port as ICec; - } - - Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called: '{1}'", + Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called '{1}'", config.ControlPortDevKey, config.ControlPortName); - return null; + return null; } /// From 1569c12450a11c8b99b1b8f6f0d917b0d35a0dde Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 20 Sep 2023 15:41:06 -0500 Subject: [PATCH 23/40] fix: Updates SetupOutputs method Corrects the port referencece to exclude `.StreamCec` when building the port. --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index cbcf2a7c..bf9f72cc 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -183,7 +183,7 @@ namespace PepperDash_Essentials_DM.Chassis var hdmiPort = new RoutingOutputPort(hdmiKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { FeedbackMatchObject = output, - Port = output.HdmiOutput.HdmiOutputPort.StreamCec + Port = output.HdmiOutput.HdmiOutputPort }; Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, name); OutputPorts.Add(hdmiPort); @@ -192,13 +192,13 @@ namespace PepperDash_Essentials_DM.Chassis var dmLitePort = new RoutingOutputPort(dmLiteKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, output, this) { FeedbackMatchObject = output, - Port = output.DmLiteOutput.DmLiteOutputPort.StreamCec + Port = output.DmLiteOutput.DmLiteOutputPort }; Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, name); OutputPorts.Add(dmLitePort); - + OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), - () => output.VideoOutFeedback.NameFeedback.StringValue)); + () => output.VideoOutFeedback.NameFeedback.StringValue)); VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); From 6c41b8e19de5a4b0a6af374afa6c83598d1dff1e Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 24 Oct 2023 15:24:44 -0500 Subject: [PATCH 24/40] fix: updates executeSwitch, add helper method 1. Updated executeSwitch object casting to resolve routing issues. 2. Added ListRoutingPorts method. --- .../Chassis/HdPsXxxController.cs | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index bf9f72cc..216f3d19 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -208,6 +208,38 @@ namespace PepperDash_Essentials_DM.Chassis } + public void ListRoutingPorts() + { + try + { + foreach (var port in InputPorts) + { + Debug.Console(0, this, @"Input Port Key: {0} +Port: {1} +Type: {2} +ConnectionType: {3} +Selector: {4} +", port.Key, port.Port, port.Type, port.ConnectionType, port.Selector); + } + + foreach (var port in OutputPorts) + { + Debug.Console(0, this, @"Output Port Key: {0} +Port: {1} +Type: {2} +ConnectionType: {3} +Selector: {4} +", port.Key, port.Port, port.Type, port.ConnectionType, port.Selector); + } + } + catch (Exception ex) + { + Debug.Console(0, this, "ListRoutingPorts Exception Message: {0}", ex.Message); + Debug.Console(0, this, "ListRoutingPorts Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) Debug.Console(0, this, "ListRoutingPorts InnerException: {0}", ex.InnerException); + } + } + #region BridgeLinking /// @@ -299,9 +331,12 @@ namespace PepperDash_Essentials_DM.Chassis /// public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) { - var input = inputSelector as HdPsXxxHdmiInput; - var output = outputSelector as HdPsXxxHdmiOutput; + //var input = inputSelector as HdPsXxxHdmiInput; + //var output = outputSelector as HdPsXxxHdmiOutput; + var input = inputSelector as HdPsXxxInput; + var output = outputSelector as HdPsXxxOutput; + Debug.Console(2, this, "ExecuteSwitch: input={0}, output={1}", input, output); if (output == null) From 53b96d54e69e2108ac9c8aa67c6f35437a3b514c Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 24 Oct 2023 15:36:04 -0500 Subject: [PATCH 25/40] fix: removes old selector casting statements --- .../Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 216f3d19..36e99bc6 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -331,9 +331,6 @@ Selector: {4} /// public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) { - //var input = inputSelector as HdPsXxxHdmiInput; - //var output = outputSelector as HdPsXxxHdmiOutput; - var input = inputSelector as HdPsXxxInput; var output = outputSelector as HdPsXxxOutput; From 6698dcb46e7cdc6824d5725ecf9528385e5fe03a Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 25 Oct 2023 15:26:42 -0500 Subject: [PATCH 26/40] refactor: update init methods and add events - Updated InitializeButton method to enable/disable buttons based on config. - Updated InitializeButtonFeedback method debug statements. - Added BaseEvent event subscription. - Added PanelStateChnage event subscription. --- .../Touchpanels/Mpc3Touchpanel.cs | 109 +++++++++++------- 1 file changed, 68 insertions(+), 41 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index 296965f9..2d36fe49 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -27,7 +27,15 @@ namespace PepperDash.Essentials.Core.Touchpanels return; } + if (_touchpanel.Registerable) + { + _touchpanel.Register(); + Debug.Console(0, this, ""); + } + + _touchpanel.BaseEvent += _touchpanel_BaseEvent; _touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange; + _touchpanel.PanelStateChange += _touchpanel_PanelStateChange; _buttons = buttons; if (_buttons == null) @@ -57,8 +65,6 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void InitializeButton(string key, KeypadButton config) { - Debug.Console(1, this, "Initializing button '{0}'...", key); - if (config == null) { Debug.Console(1, this, "Button '{0}' config is null, unable to initialize", key); @@ -69,63 +75,72 @@ namespace PepperDash.Essentials.Core.Touchpanels TryParseInt(key, out buttonNumber); var buttonEventTypes = config.EventTypes; + BoolOutputSig enabledFb = null; + BoolOutputSig disabledFb = null; switch (key) { case ("power"): { - if (buttonEventTypes == null) + if (buttonEventTypes == null || buttonEventTypes.Keys == null) _touchpanel.DisablePowerButton(); else _touchpanel.EnablePowerButton(); - break; - } - case ("volumeup"): - { - if (buttonEventTypes == null) - _touchpanel.DisableVolumeUpButton(); - - break; - } - case ("volumedown"): - { - if (buttonEventTypes == null) - _touchpanel.DisableVolumeDownButton(); - - break; - } - case ("volumefeedback"): - { + + enabledFb = _touchpanel.PowerButtonEnabledFeedBack; + disabledFb = _touchpanel.PowerButtonDisabledFeedBack; break; } + //case ("volumeup"): + // { + // break; + // } + //case ("volumedown"): + // { + // break; + // } + //case ("volumefeedback"): + // { + // break; + // } case ("mute"): { - if (buttonEventTypes == null) + if (buttonEventTypes == null || buttonEventTypes.Keys == null) _touchpanel.DisableMuteButton(); else _touchpanel.EnableMuteButton(); + + enabledFb = _touchpanel.MuteButtonEnabledFeedBack; + disabledFb = _touchpanel.MuteButtonDisabledFeedBack; + break; } default: { - if (buttonNumber == 0) + if (buttonNumber == 0 || buttonNumber > 9) break; - if (buttonEventTypes == null) + if (buttonEventTypes == null || buttonEventTypes.Keys == null) _touchpanel.DisableNumericalButton((uint)buttonNumber); else _touchpanel.EnableNumericalButton((uint)buttonNumber); + + if (_touchpanel.NumericalButtonEnabledFeedBack != null) + enabledFb = _touchpanel.NumericalButtonEnabledFeedBack[(uint)buttonNumber]; + + if (_touchpanel.NumericalButtonDisabledFeedBack != null) + disabledFb = _touchpanel.NumericalButtonDisabledFeedBack[(uint)buttonNumber]; + break; } } - Debug.Console(1, this, "Button '{0}' {1}", key, buttonEventTypes == null - ? "is disabled, verify eventTypes are configured." - : "is enabled"); + Debug.Console(0, this, "InitializeButton: key-'{0}' enabledFb-'{1}', disabledFb-'{2}'", + key, enabledFb ?? (object)"null", disabledFb ?? (object)"null"); } /// @@ -135,11 +150,11 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void InitializeButtonFeedback(string key, KeypadButton config) { - Debug.Console(1, this, "Initializing button '{0}' feedback...", key); + //Debug.Console(1, this, "Initializing button '{0}' feedback...", key); if (config == null) { - Debug.Console(1, this, "Button '{0}' config is null, unable to initialize feedback", key); + Debug.Console(1, this, "Button '{0}' config is null, skipping.", key); return; } @@ -148,9 +163,9 @@ namespace PepperDash.Essentials.Core.Touchpanels // Link up the button feedbacks to the specified device feedback var buttonFeedback = config.Feedback; - if (buttonFeedback == null) + if (buttonFeedback == null || string.IsNullOrEmpty(buttonFeedback.DeviceKey)) { - Debug.Console(1, this, "Button '{0}' feedback not configured and will not be implemented. If feedback is required, verify configuration.", + Debug.Console(1, this, "Button '{0}' feedback not configured, skipping.", key); return; } @@ -162,15 +177,15 @@ namespace PepperDash.Essentials.Core.Touchpanels var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; if (device == null) { - Debug.Console(1, this, "Button '{0}' feedback with deviceKey '{1}' not found, feedback will not be implemented. Verify feedback deviceKey is properly configured.", + Debug.Console(1, this, "Button '{0}' feedback deviceKey '{1}' not found.", key, buttonFeedback.DeviceKey); return; } - + deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); if (deviceFeedback == null) { - Debug.Console(1, this, "Button '{0}' feedback failed to get feedback property for '{1}', feedback will not be implemented. Verify feedback deviceKey is properly configured.", + Debug.Console(1, this, "Button '{0}' feedbackName property '{1}' not found.", key, buttonFeedback.FeedbackName); return; } @@ -195,12 +210,12 @@ namespace PepperDash.Essentials.Core.Touchpanels } catch (Exception ex) { - Debug.Console(0, this, "Failed to initialize button '{0}' feedback with deviceKey '{1}'. If feedback is required, verify configuration.", - key, buttonFeedback.DeviceKey); - - Debug.Console(1, this, "InitializeButtonFeedback Exception Message: {0}", ex.Message); - Debug.Console(2, this, "InitializeButtonFeedback Exception StackTrace: {0}", ex.StackTrace); - if (ex.InnerException != null) Debug.Console(2, this, "InitializeButtonFeedback Exception InnerExceptioni: {0}", ex.InnerException); + Debug.Console(1, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') Exception Message: {0}", + ex.Message, key, buttonFeedback.DeviceKey); + Debug.Console(2, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') Exception StackTrace: {0}", + ex.StackTrace, key, buttonFeedback.DeviceKey); + if (ex.InnerException != null) Debug.Console(2, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') InnerException: {0}", + ex.InnerException, key, buttonFeedback.DeviceKey); return; } @@ -259,9 +274,14 @@ namespace PepperDash.Essentials.Core.Touchpanels } } + private void _touchpanel_BaseEvent(GenericBase device, BaseEventArgs args) + { + Debug.Console(1, this, "BaseEvent: eventId-'{0}', index-'{1}'", args.EventId, args.Index); + } + private void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) { - Debug.Console(1, this, "Button {0} ({1}), {2}", args.Button.Number, args.Button.Name, args.NewButtonState); + Debug.Console(1, this, "ButtonStateChange: buttonNumber-'{0}' buttonName-'{1}', buttonState-'{2}'", args.Button.Number, args.Button.Name, args.NewButtonState); var type = args.NewButtonState.ToString(); if (_buttons.ContainsKey(args.Button.Number.ToString(CultureInfo.InvariantCulture))) @@ -274,6 +294,11 @@ namespace PepperDash.Essentials.Core.Touchpanels } } + private void _touchpanel_PanelStateChange(GenericBase device, BaseEventArgs args) + { + Debug.Console(1, this, "PanelStateChange: eventId-'{0}', index-'{1}'", args.EventId, args.Index); + } + /// /// Runs the function associated with this button/type. One of the following strings: /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased @@ -282,6 +307,8 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void Press(string buttonKey, string type) { + Debug.Console(2, this, "Press: buttonKey-'{0}', type-'{1}'", buttonKey, type); + // TODO: In future, consider modifying this to generate actions at device activation time // to prevent the need to dynamically call the method via reflection on each button press if (!_buttons.ContainsKey(buttonKey)) return; From d1d1d81165ce61ad21c7c4563ceff801c2184c30 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 25 Oct 2023 15:44:39 -0500 Subject: [PATCH 27/40] fix: update registration debug statement to include response --- .../PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index 2d36fe49..2f6074dd 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -29,8 +29,8 @@ namespace PepperDash.Essentials.Core.Touchpanels if (_touchpanel.Registerable) { - _touchpanel.Register(); - Debug.Console(0, this, ""); + var registrationResponse = _touchpanel.Register(); + Debug.Console(0, this, "touchpanel registration response: {0}", registrationResponse); } _touchpanel.BaseEvent += _touchpanel_BaseEvent; From 4da2f25c3d57aa867dac162ae6a8e4812eae5dc1 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 27 Oct 2023 12:14:07 -0500 Subject: [PATCH 28/40] fix: list available buttons on startup --- .../Touchpanels/Mpc3Touchpanel.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index 2f6074dd..44a758f8 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -55,6 +55,8 @@ namespace PepperDash.Essentials.Core.Touchpanels InitializeButton(buttonKey, buttonConfig); InitializeButtonFeedback(buttonKey, buttonConfig); } + + ListButtons(); }); } @@ -318,6 +320,23 @@ namespace PepperDash.Essentials.Core.Touchpanels foreach (var eventType in button.EventTypes[type]) DeviceJsonApi.DoDeviceAction(eventType); } + + + public void ListButtons() + { + var line = new string('-', 35); + + Debug.Console(0, this, line); + + Debug.Console(0, this, "MPC3 Controller {0} - Available Butons", Key); + + foreach (var button in _buttons) + { + Debug.Console(0, this, "Key: {0}", button.Key); + } + + Debug.Console(0, this, line); + } } /// From 1df8d3f6177efb7d5eecad054e1b0b8f6f86768e Mon Sep 17 00:00:00 2001 From: jkdevito Date: Thu, 2 Nov 2023 11:54:44 -0500 Subject: [PATCH 29/40] feat: create branch to add volume control --- .../Chassis/HdPsXxxController.cs | 35 +++++++++++++++++-- .../Config/HdPsXxxPropertiesConfig.cs | 3 ++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 36e99bc6..f676c80c 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -16,9 +16,11 @@ using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis { [Description("Wrapper class for all HdPsXxx switchers")] - public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IRoutingHasVideoInputSyncFeedbacks + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IRoutingHasVideoInputSyncFeedbacks, IHasVolumeControlWithFeedback { private readonly HdPsXxx _chassis; + private readonly string _defaultAudioKey = ""; + public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -82,6 +84,9 @@ namespace PepperDash_Essentials_DM.Chassis OutputNames = props.Outputs; SetupOutputs(OutputNames); + + if (!string.IsNullOrEmpty(props.DefaultAudioKey)) + _defaultAudioKey = props.DefaultAudioKey; } // get input priorities @@ -413,6 +418,31 @@ Selector: {4} _chassis.AutoRouteOff(); } + #region IHasVolumeWithFeedback Members + + public void VolumeUp(bool pressRelease) + { + + } + + public void VolumeDown(bool pressRelease) + { + throw new NotImplementedException(); + } + + public void SetVolume(ushort level) + { + throw new NotImplementedException(); + } + + public IntFeedback VolumeLevelFeedback { get; private set; } + + + + #endregion + + + #region Events @@ -517,6 +547,7 @@ Selector: {4} #endregion + #region Factory @@ -571,7 +602,7 @@ Selector: {4} } - #endregion + #endregion } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs index 576b74f0..9b988dd1 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs @@ -15,6 +15,9 @@ namespace PepperDash_Essentials_DM.Config [JsonProperty("outputs")] public Dictionary Outputs { get; set; } + [JsonProperty("defaultAudioKey")] + public string DefaultAudioKey { get; set; } + // "inputPriorities": "1,4,3,2" [JsonProperty("inputPriorities")] public string InputPriorities { get; set; } From 355e9cde12b76b0433018f98652cff4aa96b0be8 Mon Sep 17 00:00:00 2001 From: jkdevito Date: Thu, 2 Nov 2023 11:55:48 -0500 Subject: [PATCH 30/40] chore(wip): save updates --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index f676c80c..9a2a17f4 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Runtime.InteropServices; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM; @@ -207,6 +208,14 @@ namespace PepperDash_Essentials_DM.Chassis VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); + + var audioKey = string.Format("audioOut{0}", index); + var audioPort = new RoutingOutputPort(audioKey, eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + output, this) + { + FeedbackMatchObject = output, + Port = output.OutputPort.AudioOutput; + }; } _chassis.DMOutputChange += _chassis_OutputChange; From c528fecb9a9ead1631a68303c59308fb9171af8f Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 2 Nov 2023 17:52:27 -0500 Subject: [PATCH 31/40] feat(wip): add HdPsXxx audio control --- .../HdPsXxxAnalogAuxMixerController.cs | 98 +++++++++++++++++++ .../Chassis/HdPsXxxController.cs | 50 +++------- .../Config/HdPsXxxPropertiesConfig.cs | 4 +- .../PepperDash_Essentials_DM.csproj | 1 + 4 files changed, 114 insertions(+), 39 deletions(-) create mode 100644 essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs new file mode 100644 index 00000000..3fac2cf7 --- /dev/null +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs @@ -0,0 +1,98 @@ +using System; +using Crestron.SimplSharpPro.DM; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_DM.Chassis +{ + public class HdPsXxxAnalogAuxMixerController : IKeyed, IBasicVolumeWithFeedback + { + public string Key { get; private set; } + + public HdPsXxxAnalogAuxMixer Mixer { get; set; } + + public HdPsXxxAnalogAuxMixerController(string parent, uint mixer, HdPsXxx chassis) + { + Key = string.Format("{0}-analogMixer{1}", parent, mixer); + + Mixer = chassis.AnalogAuxiliaryMixer[mixer]; + + VolumeLevelFeedback = new IntFeedback(VolumeFeedbackFunc); + MuteFeedback = new BoolFeedback(MuteFeedbackFunc); + } + + #region Volume + + public IntFeedback VolumeLevelFeedback { get; private set; } + + protected Func VolumeFeedbackFunc + { + get { return () => Mixer.VolumeFeedback.UShortValue; } + } + + public void SetVolume(ushort level) + { + Mixer.Volume.UShortValue = level; + } + + public void VolumeUp(bool pressRelease) + { + if (pressRelease) + { + var remainingRatio = (65535 - Mixer.Volume.UShortValue)/65535; + Mixer.Volume.CreateRamp(65535, 400); + } + else + { + Mixer.Volume.StopRamp(); + } + } + + public void VolumeDown(bool pressRelease) + { + if (pressRelease) + { + var remainingRatio = Mixer.Volume.UShortValue/65535; + Mixer.Volume.CreateRamp(0, (uint)(400 * remainingRatio)); + } + else + { + Mixer.Volume.StopRamp(); + } + } + + #endregion + + + #region Mute + + private bool _isMuted; + + public BoolFeedback MuteFeedback { get; private set; } + + protected Func MuteFeedbackFunc + { + get { return () => _isMuted = Mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue; } + } + + public void MuteOn() + { + Mixer.AuxiliaryMuteControl.MuteOn(); + } + + public void MuteOff() + { + Mixer.AuxiliaryMuteControl.MuteOff(); + } + + public void MuteToggle() + { + if (_isMuted) + MuteOff(); + else + MuteOn(); + } + + #endregion + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 9a2a17f4..1cece4e4 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Runtime.InteropServices; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM; @@ -17,11 +16,9 @@ using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis { [Description("Wrapper class for all HdPsXxx switchers")] - public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IRoutingHasVideoInputSyncFeedbacks, IHasVolumeControlWithFeedback + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IRoutingHasVideoInputSyncFeedbacks { private readonly HdPsXxx _chassis; - private readonly string _defaultAudioKey = ""; - public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -86,8 +83,11 @@ namespace PepperDash_Essentials_DM.Chassis OutputNames = props.Outputs; SetupOutputs(OutputNames); - if (!string.IsNullOrEmpty(props.DefaultAudioKey)) - _defaultAudioKey = props.DefaultAudioKey; + foreach (var mixer in _chassis.AnalogAuxiliaryMixer) + { + var mixerDevice = new HdPsXxxAnalogAuxMixerController(Key, mixer.MixerNumber, _chassis); + DeviceManager.AddDevice(mixerDevice); + } } // get input priorities @@ -208,14 +208,13 @@ namespace PepperDash_Essentials_DM.Chassis VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); + } - var audioKey = string.Format("audioOut{0}", index); - var audioPort = new RoutingOutputPort(audioKey, eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, - output, this) - { - FeedbackMatchObject = output, - Port = output.OutputPort.AudioOutput; - }; + Debug.Console(0, this, "----> AnalogAuxillaryMixer.Count-{0}", _chassis.AnalogAuxiliaryMixer.Count); + foreach (var item in _chassis.AnalogAuxiliaryMixer) + { + Debug.Console(0, this, "----> AnalogAuxillaryMixer[{0}].LineMuteVolumeControl.Count-{1}", item.MixerNumber, item.LineMuteVolumeControl.Count); + Debug.Console(0, this, "----> AnalogAuxillaryMixer[{0}].SourceMuteVolumeControl.Count-{1}", item.MixerNumber, item.SourceMuteVolumeControl.Count); } _chassis.DMOutputChange += _chassis_OutputChange; @@ -427,29 +426,6 @@ Selector: {4} _chassis.AutoRouteOff(); } - #region IHasVolumeWithFeedback Members - - public void VolumeUp(bool pressRelease) - { - - } - - public void VolumeDown(bool pressRelease) - { - throw new NotImplementedException(); - } - - public void SetVolume(ushort level) - { - throw new NotImplementedException(); - } - - public IntFeedback VolumeLevelFeedback { get; private set; } - - - - #endregion - #region Events @@ -564,7 +540,7 @@ Selector: {4} { public HdSp401ControllerFactory() { - TypeNames = new List() { "hdps401", "hdps402", "hdps621", "hdps622" }; + TypeNames = new List { "hdps401", "hdps402", "hdps621", "hdps622" }; } public override EssentialsDevice BuildDevice(DeviceConfig dc) { diff --git a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs index 9b988dd1..f5eb9d39 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs @@ -15,8 +15,8 @@ namespace PepperDash_Essentials_DM.Config [JsonProperty("outputs")] public Dictionary Outputs { get; set; } - [JsonProperty("defaultAudioKey")] - public string DefaultAudioKey { get; set; } + [JsonProperty("volumeMixerId")] + public uint VolumeMixerId { get; set; } // "inputPriorities": "1,4,3,2" [JsonProperty("inputPriorities")] diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index 0011c305..5840945f 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -104,6 +104,7 @@ + From a64b5240ad2b385eb6141bcdd2eaab8d07edc942 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 3 Nov 2023 18:14:53 -0500 Subject: [PATCH 32/40] feat: add output audio controller --- .../HdPsXxxAnalogAuxMixerController.cs | 13 ++- .../Chassis/HdPsXxxController.cs | 19 ++-- .../Chassis/HdPsXxxOutputAudioController.cs | 99 +++++++++++++++++++ .../PepperDash_Essentials_DM.csproj | 1 + 4 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs index 3fac2cf7..bd6893ee 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs @@ -1,15 +1,17 @@ using System; +using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM; using PepperDash.Core; using PepperDash.Essentials.Core; namespace PepperDash_Essentials_DM.Chassis { - public class HdPsXxxAnalogAuxMixerController : IKeyed, IBasicVolumeWithFeedback + public class HdPsXxxAnalogAuxMixerController : IKeyed, + IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback // || IBasicVolumeWithFeedback { public string Key { get; private set; } - public HdPsXxxAnalogAuxMixer Mixer { get; set; } + public HdPsXxxAnalogAuxMixer Mixer { get; private set; } public HdPsXxxAnalogAuxMixerController(string parent, uint mixer, HdPsXxx chassis) { @@ -17,10 +19,17 @@ namespace PepperDash_Essentials_DM.Chassis Mixer = chassis.AnalogAuxiliaryMixer[mixer]; + Mixer.AuxMixerPropertyChange += OnAuxMixerPropertyChange; + VolumeLevelFeedback = new IntFeedback(VolumeFeedbackFunc); MuteFeedback = new BoolFeedback(MuteFeedbackFunc); } + private void OnAuxMixerPropertyChange(object sender, GenericEventArgs args) + { + Debug.Console(2, this, "AuxMixerPropertyChange: {0} > Index-{1}, EventId-{2}", sender.ToString(), args.Index, args.EventId); + } + #region Volume public IntFeedback VolumeLevelFeedback { get; private set; } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 1cece4e4..a4bef385 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -83,10 +83,15 @@ namespace PepperDash_Essentials_DM.Chassis OutputNames = props.Outputs; SetupOutputs(OutputNames); - foreach (var mixer in _chassis.AnalogAuxiliaryMixer) + foreach (var item in _chassis.HdmiDmLiteOutputs) { - var mixerDevice = new HdPsXxxAnalogAuxMixerController(Key, mixer.MixerNumber, _chassis); - DeviceManager.AddDevice(mixerDevice); + var audioDevice = new HdPsXxxOutputAudioController(Key, item.Number, _chassis); + DeviceManager.AddDevice(audioDevice); + } + foreach (var item in _chassis.AnalogAuxiliaryMixer) + { + var audioDevice = new HdPsXxxAnalogAuxMixerController(Key, item.MixerNumber, _chassis); + DeviceManager.AddDevice(audioDevice); } } @@ -180,7 +185,7 @@ namespace PepperDash_Essentials_DM.Chassis var output = item; var index = item.Number; var name = string.IsNullOrEmpty(OutputNames[index]) - ? string.Format("Output {0}", index) + ? string.Format("Port {0}", index) : OutputNames[index]; output.Name.StringValue = name; @@ -191,7 +196,7 @@ namespace PepperDash_Essentials_DM.Chassis FeedbackMatchObject = output, Port = output.HdmiOutput.HdmiOutputPort }; - Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, name); + Debug.Console(1, this, "Adding Port port: {0} - {1}", hdmiPort.Key, name); OutputPorts.Add(hdmiPort); var dmLiteKey = string.Format("dmLiteOut{0}", index); @@ -200,7 +205,7 @@ namespace PepperDash_Essentials_DM.Chassis FeedbackMatchObject = output, Port = output.DmLiteOutput.DmLiteOutputPort }; - Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, name); + Debug.Console(1, this, "Adding Port port: {0} - {1}", dmLitePort.Key, name); OutputPorts.Add(dmLitePort); OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), @@ -237,7 +242,7 @@ Selector: {4} foreach (var port in OutputPorts) { - Debug.Console(0, this, @"Output Port Key: {0} + Debug.Console(0, this, @"Port Port Key: {0} Port: {1} Type: {2} ConnectionType: {3} diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs new file mode 100644 index 00000000..9716ba1e --- /dev/null +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs @@ -0,0 +1,99 @@ +using System; +using Crestron.SimplSharpPro.DM; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_DM.Chassis +{ + public class HdPsXxxOutputAudioController : IKeyed, + IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback // || IBasicVolumeWithFeedback + { + public string Key { get; private set; } + + public HdPsXxxOutputPort Port { get; private set; } + + public HdPsXxxOutputAudioController(string parent, uint output, HdPsXxx chassis) + { + Key = string.Format("{0}-audioOut{1}", parent, output); + + Port = chassis.HdmiDmLiteOutputs[output].OutputPort; + + VolumeLevelFeedback = new IntFeedback(VolumeFeedbackFunc); + MuteFeedback = new BoolFeedback(MuteFeedbackFunc); + } + + #region Volume + + public IntFeedback VolumeLevelFeedback { get; private set; } + + protected Func VolumeFeedbackFunc + { + get { return () => Port.AudioOutput.VolumeFeedback.UShortValue; } + } + + public void SetVolume(ushort level) + { + Port.AudioOutput.Volume.UShortValue = level; + } + + public void VolumeUp(bool pressRelease) + { + if (pressRelease) + { + var remainingRatio = (65535 - Port.AudioOutput.Volume.UShortValue)/65535; + Port.AudioOutput.Volume.CreateRamp(65535, 400); + } + else + { + Port.AudioOutput.Volume.StopRamp(); + } + } + + public void VolumeDown(bool pressRelease) + { + if (pressRelease) + { + var remainingRatio = Port.AudioOutput.Volume.UShortValue/65535; + Port.AudioOutput.Volume.CreateRamp(0, (uint)(400 * remainingRatio)); + } + else + { + Port.AudioOutput.Volume.StopRamp(); + } + } + + #endregion + + + #region Mute + + private bool _isMuted; + + public BoolFeedback MuteFeedback { get; private set; } + + protected Func MuteFeedbackFunc + { + get { return () => _isMuted = Port.MuteOnFeedback.BoolValue; } + } + + public void MuteOn() + { + Port.MuteOn(); + } + + public void MuteOff() + { + Port.MuteOff(); + } + + public void MuteToggle() + { + if (_isMuted) + MuteOff(); + else + MuteOn(); + } + + #endregion + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index 5840945f..41136d0d 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -106,6 +106,7 @@ + From d713abf614dd8e3ccf330c260e2c1dbcd962bb34 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 9 Nov 2023 23:36:54 -0600 Subject: [PATCH 33/40] fix: update hd-ps audio controllers to resolve control issues --- .../HdPsXxxAnalogAuxMixerController.cs | 105 ++++++++++++++---- .../Chassis/HdPsXxxOutputAudioController.cs | 80 +++++++++---- 2 files changed, 143 insertions(+), 42 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs index bd6893ee..fc8ed0e2 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs @@ -1,4 +1,4 @@ -using System; +using Crestron.SimplSharp; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM; using PepperDash.Core; @@ -20,36 +20,72 @@ namespace PepperDash_Essentials_DM.Chassis Mixer = chassis.AnalogAuxiliaryMixer[mixer]; Mixer.AuxMixerPropertyChange += OnAuxMixerPropertyChange; + Mixer.AuxiliaryMuteControl.MuteAndVolumeControlPropertyChange += OnMuteAndVolumeControlPropertyChange; - VolumeLevelFeedback = new IntFeedback(VolumeFeedbackFunc); - MuteFeedback = new BoolFeedback(MuteFeedbackFunc); - } + VolumeLevelFeedback = new IntFeedback(() => VolumeLevel); + MuteFeedback = new BoolFeedback(() => IsMuted); - private void OnAuxMixerPropertyChange(object sender, GenericEventArgs args) - { - Debug.Console(2, this, "AuxMixerPropertyChange: {0} > Index-{1}, EventId-{2}", sender.ToString(), args.Index, args.EventId); + VolumeLevel = Mixer.VolumeFeedback.ShortValue; + IsMuted = Mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue; } #region Volume - public IntFeedback VolumeLevelFeedback { get; private set; } - - protected Func VolumeFeedbackFunc + private void OnAuxMixerPropertyChange(object sender, GenericEventArgs args) { - get { return () => Mixer.VolumeFeedback.UShortValue; } + Debug.Console(2, this, "AuxMixerPropertyChange: {0} > Index-{1}, EventId-{2}", sender.GetType().ToString(), args.Index, args.EventId); + + switch (args.EventId) + { + case (3): + { + VolumeLevel = Mixer.VolumeFeedback.ShortValue; + break; + } + } } + private const ushort CrestronLevelMin = 0; + private const ushort CrestronLevelMax = 65535; + + private const int DeviceLevelMin = -800; + private const int DeviceLevelMax = 200; + + private const int RampTime = 5000; + + private int _volumeLevel; + + public int VolumeLevel + { + get { return _volumeLevel; } + set + { + var level = value; + _volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin); + + Debug.Console(1, this, "VolumeFeedback: level-'{0}', scaled-'{1}'", level, _volumeLevel); + + VolumeLevelFeedback.FireUpdate(); + } + } + + public IntFeedback VolumeLevelFeedback { get; private set; } + public void SetVolume(ushort level) { - Mixer.Volume.UShortValue = level; + var scaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, + DeviceLevelMin); + + Debug.Console(1, this, "SetVolume: level-'{0}', scaled-'{1}'", level, scaled); + + Mixer.Volume.ShortValue = (short)scaled; } public void VolumeUp(bool pressRelease) { if (pressRelease) { - var remainingRatio = (65535 - Mixer.Volume.UShortValue)/65535; - Mixer.Volume.CreateRamp(65535, 400); + Mixer.Volume.CreateSignedRamp(DeviceLevelMax, RampTime); } else { @@ -61,8 +97,10 @@ namespace PepperDash_Essentials_DM.Chassis { if (pressRelease) { - var remainingRatio = Mixer.Volume.UShortValue/65535; - Mixer.Volume.CreateRamp(0, (uint)(400 * remainingRatio)); + //var remainingRatio = Mixer.Volume.UShortValue/CrestronLevelMax; + //Mixer.Volume.CreateRamp(CrestronLevelMin, (uint)(RampTime * remainingRatio)); + + Mixer.Volume.CreateSignedRamp(DeviceLevelMin, RampTime); } else { @@ -73,17 +111,42 @@ namespace PepperDash_Essentials_DM.Chassis #endregion + + #region Mute + private void OnMuteAndVolumeControlPropertyChange(MuteControl device, GenericEventArgs args) + { + Debug.Console(2, this, "OnMuteAndVolumeControlPropertyChange: {0} > Index-{1}, EventId-{2}", device.ToString(), args.Index, args.EventId); + + switch (args.EventId) + { + case (1): + case (2): + { + IsMuted = Mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue; + break; + } + } + } + private bool _isMuted; - public BoolFeedback MuteFeedback { get; private set; } - - protected Func MuteFeedbackFunc + public bool IsMuted { - get { return () => _isMuted = Mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue; } + get { return _isMuted; } + set + { + _isMuted = value; + + Debug.Console(1, this, "IsMuted: _isMuted-'{0}'", _isMuted); + + MuteFeedback.FireUpdate(); + } } + public BoolFeedback MuteFeedback { get; private set; } + public void MuteOn() { Mixer.AuxiliaryMuteControl.MuteOn(); @@ -96,7 +159,7 @@ namespace PepperDash_Essentials_DM.Chassis public void MuteToggle() { - if (_isMuted) + if (IsMuted) MuteOff(); else MuteOn(); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs index 9716ba1e..d8583f19 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs @@ -1,47 +1,76 @@ -using System; +using Crestron.SimplSharp; using Crestron.SimplSharpPro.DM; using PepperDash.Core; using PepperDash.Essentials.Core; namespace PepperDash_Essentials_DM.Chassis { - public class HdPsXxxOutputAudioController : IKeyed, + public class HdPsXxxOutputAudioController : IKeyed, IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback // || IBasicVolumeWithFeedback { public string Key { get; private set; } - + public HdPsXxxOutputPort Port { get; private set; } - + public HdPsXxxOutputAudioController(string parent, uint output, HdPsXxx chassis) { Key = string.Format("{0}-audioOut{1}", parent, output); - + Port = chassis.HdmiDmLiteOutputs[output].OutputPort; - VolumeLevelFeedback = new IntFeedback(VolumeFeedbackFunc); - MuteFeedback = new BoolFeedback(MuteFeedbackFunc); + VolumeLevelFeedback = new IntFeedback(() => VolumeLevel); + MuteFeedback = new BoolFeedback(() => IsMuted); + + //if(Port.AudioOutput.Volume != null) + // VolumeLevel = Port.AudioOutput.VolumeFeedback.UShortValue; + + IsMuted = Port.MuteOnFeedback.BoolValue; } #region Volume - public IntFeedback VolumeLevelFeedback { get; private set; } + private const ushort CrestronLevelMin = 0; + private const ushort CrestronLevelMax = 65535; - protected Func VolumeFeedbackFunc + private const int DeviceLevelMin = -800; + private const int DeviceLevelMax = 200; + + private const int RampTime = 5000; + + private int _volumeLevel; + + public int VolumeLevel { - get { return () => Port.AudioOutput.VolumeFeedback.UShortValue; } + get { return _volumeLevel; } + set + { + var level = value; + //_volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin); + _volumeLevel = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin); + + Debug.Console(2, this, "VolumeFeedback: level-'{0}', scaled-'{1}'", level, _volumeLevel); + + VolumeLevelFeedback.FireUpdate(); + } } + public IntFeedback VolumeLevelFeedback { get; private set; } + public void SetVolume(ushort level) { - Port.AudioOutput.Volume.UShortValue = level; + var scaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, + DeviceLevelMin); + + Debug.Console(1, this, "SetVolume: level-'{0}', scaled-'{1}'", level, scaled); + + Port.AudioOutput.Volume.ShortValue = (short)scaled; } public void VolumeUp(bool pressRelease) { if (pressRelease) { - var remainingRatio = (65535 - Port.AudioOutput.Volume.UShortValue)/65535; - Port.AudioOutput.Volume.CreateRamp(65535, 400); + Port.AudioOutput.Volume.CreateSignedRamp(DeviceLevelMax, RampTime); } else { @@ -52,9 +81,8 @@ namespace PepperDash_Essentials_DM.Chassis public void VolumeDown(bool pressRelease) { if (pressRelease) - { - var remainingRatio = Port.AudioOutput.Volume.UShortValue/65535; - Port.AudioOutput.Volume.CreateRamp(0, (uint)(400 * remainingRatio)); + { + Port.AudioOutput.Volume.CreateSignedRamp(DeviceLevelMin, RampTime); } else { @@ -65,17 +93,27 @@ namespace PepperDash_Essentials_DM.Chassis #endregion + + #region Mute private bool _isMuted; - public BoolFeedback MuteFeedback { get; private set; } + public bool IsMuted + { + get { return _isMuted; } + set + { + _isMuted = value; - protected Func MuteFeedbackFunc - { - get { return () => _isMuted = Port.MuteOnFeedback.BoolValue; } + Debug.Console(1, this, "IsMuted: _isMuted-'{0}'", _isMuted); + + MuteFeedback.FireUpdate(); + } } + public BoolFeedback MuteFeedback { get; private set; } + public void MuteOn() { Port.MuteOn(); @@ -88,7 +126,7 @@ namespace PepperDash_Essentials_DM.Chassis public void MuteToggle() { - if (_isMuted) + if (IsMuted) MuteOff(); else MuteOn(); From 1c5aca03d295c0cb07fc509a65675a3d1adab181 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Dec 2023 12:36:45 -0600 Subject: [PATCH 34/40] fix: resolves hdPsXxx audio controllers scaleWithLimits exception --- .../Chassis/HdPsXxxAnalogAuxMixerController.cs | 7 +++++-- .../Essentials_DM/Chassis/HdPsXxxController.cs | 4 +++- .../Chassis/HdPsXxxOutputAudioController.cs | 12 ++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs index fc8ed0e2..694dbb21 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs @@ -61,6 +61,9 @@ namespace PepperDash_Essentials_DM.Chassis set { var level = value; + Debug.Console(1, this, "VolumeLevel: value-'{0}', level-'{1}'", value, level); + + // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) _volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin); Debug.Console(1, this, "VolumeFeedback: level-'{0}', scaled-'{1}'", level, _volumeLevel); @@ -73,8 +76,8 @@ namespace PepperDash_Essentials_DM.Chassis public void SetVolume(ushort level) { - var scaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, - DeviceLevelMin); + // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) + var scaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin); Debug.Console(1, this, "SetVolume: level-'{0}', scaled-'{1}'", level, scaled); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index a4bef385..defe9c02 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -86,11 +86,13 @@ namespace PepperDash_Essentials_DM.Chassis foreach (var item in _chassis.HdmiDmLiteOutputs) { var audioDevice = new HdPsXxxOutputAudioController(Key, item.Number, _chassis); + Debug.Console(0, this, "HdPsXxxController: created HdPsXxxOutputAudioController Key-{0}', Output-'{1}'", audioDevice.Key, item.Number); DeviceManager.AddDevice(audioDevice); } foreach (var item in _chassis.AnalogAuxiliaryMixer) { - var audioDevice = new HdPsXxxAnalogAuxMixerController(Key, item.MixerNumber, _chassis); + var audioDevice = new HdPsXxxAnalogAuxMixerController(Key, item.MixerNumber, _chassis); + Debug.Console(0, this, "HdPsXxxController: created HdPsXxAnalogAuxMixerCOntorller Key-{0}', Output-'{1}'", audioDevice.Key, item.MixerNumber); DeviceManager.AddDevice(audioDevice); } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs index d8583f19..608f2465 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs @@ -45,8 +45,10 @@ namespace PepperDash_Essentials_DM.Chassis set { var level = value; - //_volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin); - _volumeLevel = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin); + Debug.Console(1, this, "VolumeLevel: value-'{0}', level-'{1}'", value, level); + + // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) + _volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin); Debug.Console(2, this, "VolumeFeedback: level-'{0}', scaled-'{1}'", level, _volumeLevel); @@ -58,8 +60,10 @@ namespace PepperDash_Essentials_DM.Chassis public void SetVolume(ushort level) { - var scaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, - DeviceLevelMin); + // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) + var scaled = CrestronEnvironment.ScaleWithLimits(level, + CrestronLevelMax, CrestronLevelMin, + DeviceLevelMax, DeviceLevelMin); Debug.Console(1, this, "SetVolume: level-'{0}', scaled-'{1}'", level, scaled); From 67e037880657831838d70230fc130a81da453360 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Dec 2023 12:41:45 -0600 Subject: [PATCH 35/40] fix: cleanup debug statements --- .../Chassis/HdPsXxxAnalogAuxMixerController.cs | 1 - .../Essentials_DM/Chassis/HdPsXxxController.cs | 14 +++++++------- .../Chassis/HdPsXxxOutputAudioController.cs | 5 +---- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs index 694dbb21..c6829c9b 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs @@ -61,7 +61,6 @@ namespace PepperDash_Essentials_DM.Chassis set { var level = value; - Debug.Console(1, this, "VolumeLevel: value-'{0}', level-'{1}'", value, level); // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) _volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index defe9c02..c0363387 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -86,13 +86,13 @@ namespace PepperDash_Essentials_DM.Chassis foreach (var item in _chassis.HdmiDmLiteOutputs) { var audioDevice = new HdPsXxxOutputAudioController(Key, item.Number, _chassis); - Debug.Console(0, this, "HdPsXxxController: created HdPsXxxOutputAudioController Key-{0}', Output-'{1}'", audioDevice.Key, item.Number); + Debug.Console(2, this, "Adding HdPsXxxOutputAudioController '{0}' for output '{1}'", audioDevice.Key, item.Number); DeviceManager.AddDevice(audioDevice); } foreach (var item in _chassis.AnalogAuxiliaryMixer) { var audioDevice = new HdPsXxxAnalogAuxMixerController(Key, item.MixerNumber, _chassis); - Debug.Console(0, this, "HdPsXxxController: created HdPsXxAnalogAuxMixerCOntorller Key-{0}', Output-'{1}'", audioDevice.Key, item.MixerNumber); + Debug.Console(2, this, "Adding HdPsXxAnalogAuxMixerCOntorller '{0}' for output '{1}'", audioDevice.Key, item.MixerNumber); DeviceManager.AddDevice(audioDevice); } } @@ -216,14 +216,14 @@ namespace PepperDash_Essentials_DM.Chassis VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); } - - Debug.Console(0, this, "----> AnalogAuxillaryMixer.Count-{0}", _chassis.AnalogAuxiliaryMixer.Count); + /* + Debug.Console(2, this, "----> AnalogAuxillaryMixer.Count-{0}", _chassis.AnalogAuxiliaryMixer.Count); foreach (var item in _chassis.AnalogAuxiliaryMixer) { - Debug.Console(0, this, "----> AnalogAuxillaryMixer[{0}].LineMuteVolumeControl.Count-{1}", item.MixerNumber, item.LineMuteVolumeControl.Count); - Debug.Console(0, this, "----> AnalogAuxillaryMixer[{0}].SourceMuteVolumeControl.Count-{1}", item.MixerNumber, item.SourceMuteVolumeControl.Count); + Debug.Console(2, this, "----> AnalogAuxillaryMixer[{0}].LineMuteVolumeControl.Count-{1}", item.MixerNumber, item.LineMuteVolumeControl.Count); + Debug.Console(2, this, "----> AnalogAuxillaryMixer[{0}].SourceMuteVolumeControl.Count-{1}", item.MixerNumber, item.SourceMuteVolumeControl.Count); } - + */ _chassis.DMOutputChange += _chassis_OutputChange; } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs index 608f2465..3f28d91f 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs @@ -45,7 +45,6 @@ namespace PepperDash_Essentials_DM.Chassis set { var level = value; - Debug.Console(1, this, "VolumeLevel: value-'{0}', level-'{1}'", value, level); // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) _volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin); @@ -61,9 +60,7 @@ namespace PepperDash_Essentials_DM.Chassis public void SetVolume(ushort level) { // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) - var scaled = CrestronEnvironment.ScaleWithLimits(level, - CrestronLevelMax, CrestronLevelMin, - DeviceLevelMax, DeviceLevelMin); + var scaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin); Debug.Console(1, this, "SetVolume: level-'{0}', scaled-'{1}'", level, scaled); From 5530c91b75fb907ce6033bd10f2f2758c2928cd0 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Dec 2023 16:01:15 -0600 Subject: [PATCH 36/40] refactor: HdPsXxxOutputAudioController & HdPsXxxAnalogAuxMixerController - Updated audio controllers to implement `Volume(Feedback).ShortValue` per documentation for set and get - Changed `VolumeLevel` set to private set - Removed `VolumeLevel` and `IsMuted` set from constructors --- .../HdPsXxxAnalogAuxMixerController.cs | 77 +++++++++++-------- .../Chassis/HdPsXxxController.cs | 2 +- .../Chassis/HdPsXxxOutputAudioController.cs | 67 +++++++++++----- 3 files changed, 94 insertions(+), 52 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs index c6829c9b..7d27d35b 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxAnalogAuxMixerController.cs @@ -7,39 +7,47 @@ using PepperDash.Essentials.Core; namespace PepperDash_Essentials_DM.Chassis { public class HdPsXxxAnalogAuxMixerController : IKeyed, - IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback // || IBasicVolumeWithFeedback + IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback { public string Key { get; private set; } - public HdPsXxxAnalogAuxMixer Mixer { get; private set; } + private readonly HdPsXxxAnalogAuxMixer _mixer; public HdPsXxxAnalogAuxMixerController(string parent, uint mixer, HdPsXxx chassis) { Key = string.Format("{0}-analogMixer{1}", parent, mixer); - Mixer = chassis.AnalogAuxiliaryMixer[mixer]; + _mixer = chassis.AnalogAuxiliaryMixer[mixer]; - Mixer.AuxMixerPropertyChange += OnAuxMixerPropertyChange; - Mixer.AuxiliaryMuteControl.MuteAndVolumeControlPropertyChange += OnMuteAndVolumeControlPropertyChange; + _mixer.AuxMixerPropertyChange += OnAuxMixerPropertyChange; + _mixer.AuxiliaryMuteControl.MuteAndVolumeControlPropertyChange += OnMuteAndVolumeControlPropertyChange; VolumeLevelFeedback = new IntFeedback(() => VolumeLevel); MuteFeedback = new BoolFeedback(() => IsMuted); - - VolumeLevel = Mixer.VolumeFeedback.ShortValue; - IsMuted = Mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue; } #region Volume private void OnAuxMixerPropertyChange(object sender, GenericEventArgs args) { - Debug.Console(2, this, "AuxMixerPropertyChange: {0} > Index-{1}, EventId-{2}", sender.GetType().ToString(), args.Index, args.EventId); + Debug.Console(2, this, "OnAuxMixerPropertyChange: {0} > Index-{1}, EventId-{2}", sender.ToString(), args.Index, args.EventId); switch (args.EventId) { - case (3): + case MuteAndVolumeContorlEventIds.VolumeFeedbackEventId: { - VolumeLevel = Mixer.VolumeFeedback.ShortValue; + VolumeLevel = _mixer.VolumeFeedback.ShortValue; + break; + } + case MuteAndVolumeContorlEventIds.MuteOnEventId: + case MuteAndVolumeContorlEventIds.MuteOffEventId: + { + IsMuted = _mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue; + break; + } + default: + { + Debug.Console(1, this, "OnAuxMixerPropertyChange: {0} > Index-{1}, EventId-{2} - unhandled eventId", sender.ToString(), args.Index, args.EventId); break; } } @@ -58,13 +66,12 @@ namespace PepperDash_Essentials_DM.Chassis public int VolumeLevel { get { return _volumeLevel; } - set + private set { var level = value; - // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) _volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin); - + Debug.Console(1, this, "VolumeFeedback: level-'{0}', scaled-'{1}'", level, _volumeLevel); VolumeLevelFeedback.FireUpdate(); @@ -72,26 +79,25 @@ namespace PepperDash_Essentials_DM.Chassis } public IntFeedback VolumeLevelFeedback { get; private set; } - + public void SetVolume(ushort level) { - // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) - var scaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin); + var levelScaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin); - Debug.Console(1, this, "SetVolume: level-'{0}', scaled-'{1}'", level, scaled); - - Mixer.Volume.ShortValue = (short)scaled; + Debug.Console(1, this, "SetVolume: level-'{0}', levelScaled-'{1}'", level, levelScaled); + + _mixer.Volume.ShortValue = (short)levelScaled; } public void VolumeUp(bool pressRelease) { if (pressRelease) { - Mixer.Volume.CreateSignedRamp(DeviceLevelMax, RampTime); + _mixer.Volume.CreateSignedRamp(DeviceLevelMax, RampTime); } else { - Mixer.Volume.StopRamp(); + _mixer.Volume.StopRamp(); } } @@ -99,14 +105,11 @@ namespace PepperDash_Essentials_DM.Chassis { if (pressRelease) { - //var remainingRatio = Mixer.Volume.UShortValue/CrestronLevelMax; - //Mixer.Volume.CreateRamp(CrestronLevelMin, (uint)(RampTime * remainingRatio)); - - Mixer.Volume.CreateSignedRamp(DeviceLevelMin, RampTime); + _mixer.Volume.CreateSignedRamp(DeviceLevelMin, RampTime); } else { - Mixer.Volume.StopRamp(); + _mixer.Volume.StopRamp(); } } @@ -123,12 +126,22 @@ namespace PepperDash_Essentials_DM.Chassis switch (args.EventId) { - case (1): - case (2): + case MuteAndVolumeContorlEventIds.VolumeFeedbackEventId: { - IsMuted = Mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue; + VolumeLevel = _mixer.VolumeFeedback.ShortValue; break; } + case MuteAndVolumeContorlEventIds.MuteOnEventId: + case MuteAndVolumeContorlEventIds.MuteOffEventId: + { + IsMuted = _mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue; + break; + } + default: + { + Debug.Console(1, this, "OnMuteAndVolumeControlPropertyChange: {0} > Index-{1}, EventId-{2} - unhandled eventId", device.ToString(), args.Index, args.EventId); + break; + } } } @@ -151,12 +164,12 @@ namespace PepperDash_Essentials_DM.Chassis public void MuteOn() { - Mixer.AuxiliaryMuteControl.MuteOn(); + _mixer.AuxiliaryMuteControl.MuteOn(); } public void MuteOff() { - Mixer.AuxiliaryMuteControl.MuteOff(); + _mixer.AuxiliaryMuteControl.MuteOff(); } public void MuteToggle() diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index c0363387..6b0f8520 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -88,7 +88,7 @@ namespace PepperDash_Essentials_DM.Chassis var audioDevice = new HdPsXxxOutputAudioController(Key, item.Number, _chassis); Debug.Console(2, this, "Adding HdPsXxxOutputAudioController '{0}' for output '{1}'", audioDevice.Key, item.Number); DeviceManager.AddDevice(audioDevice); - } + } foreach (var item in _chassis.AnalogAuxiliaryMixer) { var audioDevice = new HdPsXxxAnalogAuxMixerController(Key, item.MixerNumber, _chassis); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs index 3f28d91f..57067bde 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxOutputAudioController.cs @@ -6,25 +6,56 @@ using PepperDash.Essentials.Core; namespace PepperDash_Essentials_DM.Chassis { public class HdPsXxxOutputAudioController : IKeyed, - IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback // || IBasicVolumeWithFeedback + IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback { public string Key { get; private set; } - public HdPsXxxOutputPort Port { get; private set; } + private readonly HdPsXxxHdmiDmLiteOutputMixer _mixer; // volume/volumeFeedback + private readonly HdPsXxxOutputPort _port; // mute/muteFeedback public HdPsXxxOutputAudioController(string parent, uint output, HdPsXxx chassis) { Key = string.Format("{0}-audioOut{1}", parent, output); - Port = chassis.HdmiDmLiteOutputs[output].OutputPort; + _port = chassis.HdmiDmLiteOutputs[output].OutputPort; + _mixer = chassis.HdmiDmLiteOutputs[output].Mixer; + + chassis.DMOutputChange += ChassisOnDmOutputChange; VolumeLevelFeedback = new IntFeedback(() => VolumeLevel); MuteFeedback = new BoolFeedback(() => IsMuted); + } - //if(Port.AudioOutput.Volume != null) - // VolumeLevel = Port.AudioOutput.VolumeFeedback.UShortValue; + private void ChassisOnDmOutputChange(Switch device, DMOutputEventArgs args) + { + switch (args.EventId) + { + case (DMOutputEventIds.VolumeEventId): + { + Debug.Console(2, this, "HdPsXxxOutputAudioController: {0} > Index-{1}, Number-{3}, EventId-{2} - AudioMute/UnmuteEventId", + device.ToString(), args.Index, args.EventId, args.Number); - IsMuted = Port.MuteOnFeedback.BoolValue; + VolumeLevel = _mixer.VolumeFeedback.ShortValue; + + break; + } + case DMOutputEventIds.MuteOnEventId: + case DMOutputEventIds.MuteOffEventId: + { + Debug.Console(2, this, "HdPsXxxOutputAudioController: {0} > Index-{1}, Number-{3}, EventId-{2} - MuteOnEventId/MuteOffEventId", + device.ToString(), args.Index, args.EventId, args.Number); + + IsMuted = _port.MuteOnFeedback.BoolValue; + + break; + } + default: + { + Debug.Console(1, this, "HdPsXxxOutputAudioController: {0} > Index-{1}, Number-{3}, EventId-{2} - unhandled eventId", + device.ToString(), args.Index, args.EventId, args.Number); + break; + } + } } #region Volume @@ -42,11 +73,10 @@ namespace PepperDash_Essentials_DM.Chassis public int VolumeLevel { get { return _volumeLevel; } - set + private set { var level = value; - - // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) + _volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin); Debug.Console(2, this, "VolumeFeedback: level-'{0}', scaled-'{1}'", level, _volumeLevel); @@ -59,23 +89,22 @@ namespace PepperDash_Essentials_DM.Chassis public void SetVolume(ushort level) { - // ScaleWithLimits(inputValue, InputUpperBound, InputLowerBound, OutputUpperBound, OutputLowerBound) - var scaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin); + var levelScaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin); - Debug.Console(1, this, "SetVolume: level-'{0}', scaled-'{1}'", level, scaled); + Debug.Console(1, this, "SetVolume: level-'{0}', levelScaled-'{1}'", level, levelScaled); - Port.AudioOutput.Volume.ShortValue = (short)scaled; + _mixer.Volume.ShortValue = (short)levelScaled; } public void VolumeUp(bool pressRelease) { if (pressRelease) { - Port.AudioOutput.Volume.CreateSignedRamp(DeviceLevelMax, RampTime); + _mixer.Volume.CreateSignedRamp(DeviceLevelMax, RampTime); } else { - Port.AudioOutput.Volume.StopRamp(); + _mixer.Volume.StopRamp(); } } @@ -83,11 +112,11 @@ namespace PepperDash_Essentials_DM.Chassis { if (pressRelease) { - Port.AudioOutput.Volume.CreateSignedRamp(DeviceLevelMin, RampTime); + _mixer.Volume.CreateSignedRamp(DeviceLevelMin, RampTime); } else { - Port.AudioOutput.Volume.StopRamp(); + _mixer.Volume.StopRamp(); } } @@ -117,12 +146,12 @@ namespace PepperDash_Essentials_DM.Chassis public void MuteOn() { - Port.MuteOn(); + _port.MuteOn(); } public void MuteOff() { - Port.MuteOff(); + _port.MuteOff(); } public void MuteToggle() From 533ca05ac20f1257df85be6aaabf97fd2fe06d9c Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 14 Dec 2023 12:43:46 -0600 Subject: [PATCH 37/40] feat: adds additional dm input/output event cases to event handlers --- .../Chassis/HdPsXxxController.cs | 146 ++++++++++++------ 1 file changed, 99 insertions(+), 47 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 6b0f8520..45510a88 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -88,7 +88,7 @@ namespace PepperDash_Essentials_DM.Chassis var audioDevice = new HdPsXxxOutputAudioController(Key, item.Number, _chassis); Debug.Console(2, this, "Adding HdPsXxxOutputAudioController '{0}' for output '{1}'", audioDevice.Key, item.Number); DeviceManager.AddDevice(audioDevice); - } + } foreach (var item in _chassis.AnalogAuxiliaryMixer) { var audioDevice = new HdPsXxxAnalogAuxMixerController(Key, item.MixerNumber, _chassis); @@ -111,7 +111,7 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "Failed to setup inputs, properties are null"); return; } - + // iterate through HDMI inputs foreach (var item in _chassis.HdmiInputs) { @@ -124,7 +124,7 @@ namespace PepperDash_Essentials_DM.Chassis input.Name.StringValue = name; - InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), () => InputNames[index])); var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) @@ -134,10 +134,10 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "Adding Input port: {0} - {1}", port.Key, name); InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), () => input.VideoDetectedFeedback.BoolValue)); } @@ -147,13 +147,13 @@ namespace PepperDash_Essentials_DM.Chassis var input = item; var index = item.Number; var key = string.Format("dmLiteIn{0}", index); - var name = string.IsNullOrEmpty(InputNames[index]) - ? string.Format("DM Input {0}", index) + var name = string.IsNullOrEmpty(InputNames[index]) + ? string.Format("DM Input {0}", index) : InputNames[index]; input.Name.StringValue = name; - InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), () => InputNames[index])); var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) @@ -163,10 +163,10 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(0, this, "Adding Input port: {0} - {1}", port.Key, name); InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), () => input.VideoDetectedFeedback.BoolValue)); } @@ -186,10 +186,10 @@ namespace PepperDash_Essentials_DM.Chassis { var output = item; var index = item.Number; - var name = string.IsNullOrEmpty(OutputNames[index]) - ? string.Format("Port {0}", index) + var name = string.IsNullOrEmpty(OutputNames[index]) + ? string.Format("Port {0}", index) : OutputNames[index]; - + output.Name.StringValue = name; var hdmiKey = string.Format("hdmiOut{0}", index); @@ -209,11 +209,11 @@ namespace PepperDash_Essentials_DM.Chassis }; Debug.Console(1, this, "Adding Port port: {0} - {1}", dmLitePort.Key, name); OutputPorts.Add(dmLitePort); - - OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), - () => output.VideoOutFeedback.NameFeedback.StringValue)); - VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), + OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => output.VideoOutFeedback.NameFeedback.StringValue)); + + VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); } /* @@ -352,8 +352,8 @@ Selector: {4} public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) { var input = inputSelector as HdPsXxxInput; - var output = outputSelector as HdPsXxxOutput; - + var output = outputSelector as HdPsXxxOutput; + Debug.Console(2, this, "ExecuteSwitch: input={0}, output={1}", input, output); if (output == null) @@ -456,24 +456,58 @@ Selector: {4} // _chassis input change event private void _chassis_InputChange(Switch device, DMInputEventArgs args) { - var eventId = args.EventId; - - switch (eventId) + switch (args.EventId) { + case DMInputEventIds.RemoteTransmitterDetectedEventId: + { + // signal found on HD-PSXxx > Inputs > Inputs DM Lite X + Debug.Console(2, this, "{0} DM Input Event ID {1}-RemoteTransmitterDetected | Number {2}", + device.ToString(), args.EventId, args.Number); + break; + } + case DMInputEventIds.SourceSyncEventId: + { + // signal found on HD-PSXxx > Inputs > HDMI/DM Lite X + Debug.Console(1, this, "{0} DM Input Event ID {1}-SourceSync | Number {2}: Updating VideoInputSyncFeedbacks", + device.ToString(), args.EventId, args.Number); + + var input = args.Number; + + var feedback = VideoInputSyncFeedbacks[(int)input]; + if (feedback == null) return; + + feedback.FireUpdate(); + + //foreach (var item in VideoInputSyncFeedbacks) + //{ + // item.FireUpdate(); + //} + break; + } case DMInputEventIds.VideoDetectedEventId: { - Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", eventId); - foreach (var item in VideoInputSyncFeedbacks) - { - item.FireUpdate(); - } + Debug.Console(1, this, "{0} DM Input Event ID {1}-VideoDetected | Number {2}: Updating VideoInputSyncFeedbacks", + device.ToString(), args.EventId, args.Number); + + var input = args.Number; + + var feedback = VideoInputSyncFeedbacks[(int) input]; + if (feedback == null) return; + + feedback.FireUpdate(); + + //foreach (var item in VideoInputSyncFeedbacks) + //{ + // item.FireUpdate(); + //} break; } case DMInputEventIds.InputNameFeedbackEventId: case DMInputEventIds.InputNameEventId: case DMInputEventIds.NameFeedbackEventId: { - Debug.Console(1, this, "Event ID {0}: Updating name feedbacks", eventId); + Debug.Console(1, this, "{0} DM Input Event ID {1}-Name | Number {2}: Updating name feedbacks", + device.ToString(), args.EventId, args.Number); var input = args.Number; var name = _chassis.HdmiInputs[input].NameFeedback.StringValue; @@ -483,7 +517,8 @@ Selector: {4} } default: { - Debug.Console(1, this, "Uhandled DM Input Event ID {0}", eventId); + Debug.Console(1, this, "{0} DM Input Event ID {1} | Number {2}: Uhandled", + device.ToString(), args.EventId, args.Number); break; } } @@ -491,33 +526,50 @@ Selector: {4} OnDmInputChange(args); } - // _chassis output change event private void _chassis_OutputChange(Switch device, DMOutputEventArgs args) { - if (args.EventId != DMOutputEventIds.VideoOutEventId) return; + switch (args.EventId) + { + case DMOutputEventIds.VideoOutEventId: + { + var output = args.Number; - var output = args.Number; + var input = _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback == null + ? 0 + : _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback.Number; - var input = _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback == null - ? 0 - : _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback.Number; + var outputName = OutputNames[output]; - var outputName = OutputNames[output]; + var feedback = VideoOutputRouteFeedbacks[outputName]; + if (feedback == null) return; - var feedback = VideoOutputRouteFeedbacks[outputName]; - if (feedback == null) return; + var inputPort = InputPorts.FirstOrDefault( + p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback); - var inputPort = InputPorts.FirstOrDefault( - p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback); + var outputPort = OutputPorts.FirstOrDefault( + p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output]); - var outputPort = OutputPorts.FirstOrDefault( - p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output]); + feedback.FireUpdate(); - feedback.FireUpdate(); + OnSwitchChange(new RoutingNumericEventArgs(output, input, outputPort, inputPort, eRoutingSignalType.AudioVideo)); - OnSwitchChange(new RoutingNumericEventArgs( - output, input, outputPort, inputPort, eRoutingSignalType.AudioVideo)); + break; + } + case DMOutputEventIds.RemoteReceiverDetectedEventId: + { + // signal found on HD-PSXxx > Output[s] > Output [X] > DM Lite [X] + Debug.Console(2, this, "{0} DM Output Event Id {1} | Number:{2} | Index {3}: RemoteRecevierDetectedEventId", + device.ToString(), args.EventId, args.Number, args.Index); + break; + } + default: + { + Debug.Console(2, this, "{0} DM Output Event Id {1} | Number:{2} | Index:{3}: Unhandled", + device.ToString(), args.EventId, args.Number, args.Index); + break; + } + } } @@ -543,9 +595,9 @@ Selector: {4} #region Factory - public class HdSp401ControllerFactory : EssentialsDeviceFactory + public class HdPsXxxControllerFactory : EssentialsDeviceFactory { - public HdSp401ControllerFactory() + public HdPsXxxControllerFactory() { TypeNames = new List { "hdps401", "hdps402", "hdps621", "hdps622" }; } From 19f2c6aa7976580b8da1695a8c5459fddb63ba79 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 14 Dec 2023 16:32:22 -0600 Subject: [PATCH 38/40] fix: update dm event handlers, adds debug statements --- .../Chassis/HdPsXxxController.cs | 48 ++++++------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 45510a88..c0723893 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -138,7 +138,7 @@ namespace PepperDash_Essentials_DM.Chassis () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), - () => input.VideoDetectedFeedback.BoolValue)); + () => input.InputPort.SyncDetectedFeedback.BoolValue)); } // iterate through DM Lite inputs @@ -167,7 +167,7 @@ namespace PepperDash_Essentials_DM.Chassis () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), - () => input.VideoDetectedFeedback.BoolValue)); + () => input.InputPort.SyncDetectedFeedback.BoolValue)); } _chassis.DMInputChange += _chassis_InputChange; @@ -459,17 +459,18 @@ Selector: {4} switch (args.EventId) { case DMInputEventIds.RemoteTransmitterDetectedEventId: - { + { // signal found on HD-PSXxx > Inputs > Inputs DM Lite X Debug.Console(2, this, "{0} DM Input Event ID {1}-RemoteTransmitterDetected | Number {2}", device.ToString(), args.EventId, args.Number); break; } - case DMInputEventIds.SourceSyncEventId: + case DMInputEventIds.SourceSyncEventId: // id-14 + case DMInputEventIds.VideoDetectedEventId: // id-9 { // signal found on HD-PSXxx > Inputs > HDMI/DM Lite X Debug.Console(1, this, "{0} DM Input Event ID {1}-SourceSync | Number {2}: Updating VideoInputSyncFeedbacks", - device.ToString(), args.EventId, args.Number); + device.Name, args.EventId, args.Number); var input = args.Number; @@ -478,28 +479,6 @@ Selector: {4} feedback.FireUpdate(); - //foreach (var item in VideoInputSyncFeedbacks) - //{ - // item.FireUpdate(); - //} - break; - } - case DMInputEventIds.VideoDetectedEventId: - { - Debug.Console(1, this, "{0} DM Input Event ID {1}-VideoDetected | Number {2}: Updating VideoInputSyncFeedbacks", - device.ToString(), args.EventId, args.Number); - - var input = args.Number; - - var feedback = VideoInputSyncFeedbacks[(int) input]; - if (feedback == null) return; - - feedback.FireUpdate(); - - //foreach (var item in VideoInputSyncFeedbacks) - //{ - // item.FireUpdate(); - //} break; } case DMInputEventIds.InputNameFeedbackEventId: @@ -507,7 +486,7 @@ Selector: {4} case DMInputEventIds.NameFeedbackEventId: { Debug.Console(1, this, "{0} DM Input Event ID {1}-Name | Number {2}: Updating name feedbacks", - device.ToString(), args.EventId, args.Number); + device.Name, args.EventId, args.Number); var input = args.Number; var name = _chassis.HdmiInputs[input].NameFeedback.StringValue; @@ -518,7 +497,7 @@ Selector: {4} default: { Debug.Console(1, this, "{0} DM Input Event ID {1} | Number {2}: Uhandled", - device.ToString(), args.EventId, args.Number); + device.Name, args.EventId, args.Number); break; } } @@ -533,6 +512,9 @@ Selector: {4} { case DMOutputEventIds.VideoOutEventId: { + Debug.Console(2, this, "{0} DM Output Event Id {1} | Number {2} | Index {3}: VideoOutEventId", + device.Name, args.EventId, args.Number, args.Index); + var output = args.Number; var input = _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback == null @@ -559,14 +541,14 @@ Selector: {4} case DMOutputEventIds.RemoteReceiverDetectedEventId: { // signal found on HD-PSXxx > Output[s] > Output [X] > DM Lite [X] - Debug.Console(2, this, "{0} DM Output Event Id {1} | Number:{2} | Index {3}: RemoteRecevierDetectedEventId", - device.ToString(), args.EventId, args.Number, args.Index); + Debug.Console(2, this, "{0} DM Output Event Id {1} | Number {2} | Index {3}: RemoteRecevierDetectedEventId", + device.Name, args.EventId, args.Number, args.Index); break; } default: { - Debug.Console(2, this, "{0} DM Output Event Id {1} | Number:{2} | Index:{3}: Unhandled", - device.ToString(), args.EventId, args.Number, args.Index); + Debug.Console(2, this, "{0} DM Output Event Id {1} | Number {2} | Index:{3}: Unhandled", + device.Name, args.EventId, args.Number, args.Index); break; } } From b24501642079c1f936f6c678aac474e4c7f651e6 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 14 Dec 2023 17:02:14 -0600 Subject: [PATCH 39/40] fix: updated dminputchange event debug message --- .../Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index c0723893..c267acea 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -469,7 +469,7 @@ Selector: {4} case DMInputEventIds.VideoDetectedEventId: // id-9 { // signal found on HD-PSXxx > Inputs > HDMI/DM Lite X - Debug.Console(1, this, "{0} DM Input Event ID {1}-SourceSync | Number {2}: Updating VideoInputSyncFeedbacks", + Debug.Console(1, this, "{0} DM Input Event ID {1} | Number {2}: Updating VideoInputSyncFeedbacks", device.Name, args.EventId, args.Number); var input = args.Number; From 8c1553a0269e36760fea6cdb1469201d8b49eae9 Mon Sep 17 00:00:00 2001 From: jtalborough Date: Mon, 26 Feb 2024 13:22:35 -0500 Subject: [PATCH 40/40] fix: Update PepperDashCore version to 1.3.3-hotfix-390 --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index fa36e07d..eff6d8ce 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - +