From 96e3d52b95543e46be0b88656e6de28e3b22a1be Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 09:43:59 -0400 Subject: [PATCH 01/30] Switch DMPS units to only wait until devices are registered before continuing. No need to wait for devices to be activated. --- PepperDashEssentials/ControlSystem.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 53ea9e13..dd8f3d5a 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -53,14 +53,14 @@ namespace PepperDash.Essentials // to allow any HD-BaseT DM endpoints to register first. if (Global.ControlSystemIsDmpsType) { - Debug.Console(2, "******************* InitializeSystem() Entering **********************"); + Debug.Console(1, "******************* InitializeSystem() Entering **********************"); _initializeEvent = new CEvent(); - DeviceManager.AllDevicesActivated += (o, a) => + DeviceManager.AllDevicesRegistered += (o, a) => { _initializeEvent.Set(); - Debug.Console(2, "******************* InitializeSystem() Exiting **********************"); + Debug.Console(1, "******************* InitializeSystem() Exiting **********************"); }; _initializeEvent.Wait(30000); From dfc0915fe0edff27d76a3bece126065649bb34fd Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 09:56:40 -0400 Subject: [PATCH 02/30] Adds DM switcher name to bridge --- .../Bridges/JoinMaps/DmChassisControllerJoinMap.cs | 4 ++++ .../Essentials_DM/Chassis/DmChassisController.cs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmChassisControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmChassisControllerJoinMap.cs index 3582e6cf..114a8a9d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmChassisControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmChassisControllerJoinMap.cs @@ -24,6 +24,10 @@ namespace PepperDash.Essentials.Core.Bridges JoinType = eJoinType.Digital }); + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DM Chassis Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("SystemId")] public JoinDataComplete SystemId = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, new JoinMetadata { Description = "DM Chassis SystemId Get/Set/Trigger/", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.DigitalAnalog }); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs index ef7fc577..60ef9d69 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs @@ -1482,6 +1482,8 @@ namespace PepperDash.Essentials.DM LinkChassisToApi(trilist, joinMap); + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; + // Link up inputs & outputs for (uint i = 1; i <= Chassis.NumberOfOutputs; i++) { From 60b6cea69750745f128f3e7e45a158b4a3fc7f22 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:13:02 -0400 Subject: [PATCH 03/30] Adds digital audio output volume control for DMPS to bridge --- .../DmpsAudioOutputControllerJoinMap.cs | 4 + .../Chassis/DmpsAudioOutputController.cs | 116 ++++++++++--- .../Chassis/DmpsRoutingController.cs | 156 ++++++++++-------- 3 files changed, 179 insertions(+), 97 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs index c7d5c0e5..a6100700 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs @@ -17,6 +17,10 @@ namespace PepperDash.Essentials.Core.Bridges public JoinDataComplete MixerPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, new JoinMetadata { Description = "Mixer Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("MixerEqPresetRecall")] + public JoinDataComplete MixerEqPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Mixer Eq Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("MasterVolumeMuteOn")] public JoinDataComplete MasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "Master Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs index 751c1a5a..60943270 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs @@ -33,36 +33,44 @@ namespace PepperDash.Essentials.DM : base(key, name) { OutputCard = card; - OutputCard.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); + SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + if (card is Card.Dmps3ProgramOutput) { - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3ProgramOutput).OutputMixer); - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + var output = card as Card.Dmps3ProgramOutput; + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); } else if (card is Card.Dmps3Aux1Output) { - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3Aux1Output).OutputMixer); - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + var output = card as Card.Dmps3Aux1Output; + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); } else if (card is Card.Dmps3Aux2Output) { - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3Aux2Output).OutputMixer); - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + var output = card as Card.Dmps3Aux2Output; + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); } - else //Digital Outputs + else if (card is Card.Dmps3DigitalMixOutput) { - MasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Master); - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + var output = card as Card.Dmps3DigitalMixOutput; + MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + } + else if (card is Card.Dmps3HdmiOutput) + { + var output = card as Card.Dmps3HdmiOutput; + MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + } + else if (card is Card.Dmps3DmOutput) + { + var output = card as Card.Dmps3DmOutput; + MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); } } @@ -185,6 +193,11 @@ namespace PepperDash.Essentials.DM { trilist.SetUShortSigAction(joinMap.MixerPresetRecall.JoinNumber, mixer.RecallPreset); } + var eq = MasterVolumeLevel as DmpsAudioOutputWithMixerAndEq; + if (eq != null) + { + trilist.SetUShortSigAction(joinMap.MixerEqPresetRecall.JoinNumber, eq.RecallEqPreset); + } } if (SourceVolumeLevel != null) @@ -234,11 +247,27 @@ namespace PepperDash.Essentials.DM } } + public class DmpsAudioOutputWithMixerAndEq : DmpsAudioOutputWithMixer + { + private CrestronControlSystem.Dmps3OutputEqualizer Eq; + public DmpsAudioOutputWithMixerAndEq(Card.Dmps3OutputBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputMixer mixer, CrestronControlSystem.Dmps3OutputEqualizer eq) + : base(output, type, mixer) + { + Eq = eq; + } + + public void RecallEqPreset(ushort preset) + { + Eq.PresetNumber.UShortValue = preset; + Eq.RecallPreset(); + } + } + public class DmpsAudioOutputWithMixer : DmpsAudioOutput { - CrestronControlSystem.Dmps3OutputMixerWithMonoAndStereo Mixer; + IDmps3OutputMixer Mixer; - public DmpsAudioOutputWithMixer(Card.Dmps3OutputBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputMixerWithMonoAndStereo mixer) + public DmpsAudioOutputWithMixer(Card.Dmps3OutputBase output, eDmpsLevelType type, IDmps3OutputMixer mixer) : base(output, type) { Mixer = mixer; @@ -266,23 +295,47 @@ namespace PepperDash.Essentials.DM public void RecallPreset(ushort preset) { - Debug.Console(1, "DMPS Recalling Preset {0}", preset); - Mixer.PresetNumber.UShortValue = preset; - Mixer.RecallPreset(); + if (Mixer is CrestronControlSystem.Dmps3OutputMixer) + { + var presetMixer = Mixer as CrestronControlSystem.Dmps3OutputMixer; + Debug.Console(1, "DMPS Recalling Preset {0}", preset); + presetMixer.PresetNumber.UShortValue = preset; + presetMixer.RecallPreset(); + + //Recall startup volume for main volume level as DMPS3(non-4K) presets don't affect the main volume + RecallStartupVolume(); + } + else if (Mixer is CrestronControlSystem.Dmps3AttachableOutputMixer) + { + var presetMixer = Mixer as CrestronControlSystem.Dmps3AttachableOutputMixer; + Debug.Console(1, "DMPS Recalling Preset {0}", preset); + presetMixer.PresetNumber.UShortValue = preset; + presetMixer.RecallPreset(); + } + + } + + public void RecallStartupVolume() + { + ushort startupVol = Mixer.StartupVolumeFeedback.UShortValue; + //Reset startup vol due to bug on DMPS3 where getting the value from above method clears the startup volume + Mixer.StartupVolume.UShortValue = startupVol; + Debug.Console(1, "DMPS Recalling {0} Startup Volume {1}", Output.Name, startupVol); + SetVolume(startupVol); + MuteOff(); } } public class DmpsAudioOutput : IBasicVolumeWithFeedback { - Card.Dmps3OutputBase Output; - eDmpsLevelType Type; - UShortInputSig Level; - + private UShortInputSig Level; + protected Card.Dmps3OutputBase Output; private bool EnableVolumeSend; private ushort VolumeLevelInput; protected short MinLevel { get; set; } protected short MaxLevel { get; set; } + public eDmpsLevelType Type { get; private set; } public BoolFeedback MuteFeedback { get; private set; } public IntFeedback VolumeLevelFeedback { get; private set; } public IntFeedback VolumeLevelScaledFeedback { get; private set; } @@ -411,10 +464,13 @@ namespace PepperDash.Essentials.DM public void SetVolumeScaled(ushort level) { Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} level:{1} min:{2} max:{3}", Output.Name, level.ToString(), MinLevel.ToString(), MaxLevel.ToString()); - VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel); - if (EnableVolumeSend == true) + if (ushort.MaxValue + MinLevel != 0) { - Level.UShortValue = VolumeLevelInput; + VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel); + if (EnableVolumeSend == true) + { + Level.UShortValue = VolumeLevelInput; + } } } @@ -422,7 +478,13 @@ namespace PepperDash.Essentials.DM { short signedLevel = (short)level; Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} feedback:{1} min:{2} max:{3}", Output.Name, signedLevel.ToString(), MinLevel.ToString(), MaxLevel.ToString()); - return (ushort)((signedLevel - MinLevel) * ushort.MaxValue / (MaxLevel - MinLevel)); + + if (MaxLevel - MinLevel != 0) + { + return (ushort)((signedLevel - MinLevel) * ushort.MaxValue / (MaxLevel - MinLevel)); + } + else + return (ushort)MinLevel; } public void SendScaledVolume(bool pressRelease) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index f6592699..22dfc195 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -481,69 +481,76 @@ namespace PepperDash.Essentials.DM { foreach (var card in Dmps.SwitcherOutputs) { - Debug.Console(1, this, "Output Card Type: {0}", card.CardInputOutputType); - - var outputCard = card as DMOutput; - - if (outputCard == null) + try { - Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType); - continue; - } + Debug.Console(1, this, "Output Card Type: {0}", card.CardInputOutputType); - Debug.Console(1, this, "Adding Output Card Number {0} Type: {1}", outputCard.Number, outputCard.CardInputOutputType.ToString()); - VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() => - { - if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; } - return 0; - ; - }); - AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() => - { - try + var outputCard = card as DMOutput; + + if (outputCard == null) { - if (outputCard.AudioOutFeedback != null) - { - return (ushort) outputCard.AudioOutFeedback.Number; - } + Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType); + continue; + } + + Debug.Console(1, this, "Adding Output Card Number {0} Type: {1}", outputCard.Number, outputCard.CardInputOutputType.ToString()); + VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() => + { + if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; } return 0; - } - catch (NotSupportedException) + ; + }); + AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() => { - return (ushort) outputCard.AudioOutSourceFeedback; - } - }); + try + { + if (outputCard.AudioOutFeedback != null) + { + return (ushort)outputCard.AudioOutFeedback.Number; + } + return 0; + } + catch (NotSupportedException) + { + return (ushort)outputCard.AudioOutSourceFeedback; + } + }); - OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => + OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => + { + if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) + { + Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue); + return outputCard.NameFeedback.StringValue; + } + return ""; + }); + + OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => + { + if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null) + { + return outputCard.VideoOutFeedback.NameFeedback.StringValue; + } + return NoRouteText; + }); + OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => + { + if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) + { + return outputCard.AudioOutFeedback.NameFeedback.StringValue; + } + return NoRouteText; + }); + + OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => outputCard.EndpointOnlineFeedback); + + AddOutputCard(outputCard.Number, outputCard); + } + catch (Exception ex) { - if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) - { - Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue); - return outputCard.NameFeedback.StringValue; - } - return ""; - }); - - OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => - { - if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null) - { - return outputCard.VideoOutFeedback.NameFeedback.StringValue; - } - return NoRouteText; - }); - OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => - { - if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) - { - return outputCard.AudioOutFeedback.NameFeedback.StringValue; - } - return NoRouteText; - }); - - OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => outputCard.EndpointOnlineFeedback); - - AddOutputCard(outputCard.Number, outputCard); + Debug.LogError(Debug.ErrorLogLevel.Error, string.Format("DMPS Controller exception creating output card: {0}", ex)); + } } } @@ -697,6 +704,9 @@ namespace PepperDash.Essentials.DM var cecPort = hdmiOutputCard.HdmiOutputPort; AddHdmiOutputPort(number, cecPort); + + var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number), string.Format("Hdmi Audio Output {0}", number), outputCard as Card.Dmps3HdmiOutput); + DeviceManager.AddDevice(audioOutput); } else if (outputCard is Card.Dmps3HdmiOutputBackend) { @@ -709,6 +719,9 @@ namespace PepperDash.Essentials.DM else if (outputCard is Card.Dmps3DmOutput) { AddDmOutputPort(number); + + var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number), string.Format("Dm Audio Output {0}", number), outputCard as Card.Dmps3DmOutput); + DeviceManager.AddDevice(audioOutput); } else if (outputCard is Card.Dmps3DmOutputBackend) { @@ -727,22 +740,22 @@ namespace PepperDash.Essentials.DM switch (outputCard.CardInputOutputType) { case eCardInputOutputType.Dmps3Aux1Output: - { - AddAudioOnlyOutputPort(number, "Aux1"); + { + AddAudioOnlyOutputPort(number, "Aux1"); - var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux1Output); + var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux1Output); - DeviceManager.AddDevice(aux1Output); - } + DeviceManager.AddDevice(aux1Output); + } break; case eCardInputOutputType.Dmps3Aux2Output: - { - AddAudioOnlyOutputPort(number, "Aux2"); + { + AddAudioOnlyOutputPort(number, "Aux2"); - var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux2Output); + var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux2Output); - DeviceManager.AddDevice(aux2Output); - } + DeviceManager.AddDevice(aux2Output); + } break; } } @@ -766,6 +779,10 @@ namespace PepperDash.Essentials.DM { AddAudioOnlyOutputPort(number, "Dialer"); } + else if (outputCard is Card.Dmps3AecOutput) + { + AddAudioOnlyOutputPort(number, "Aec"); + } else if (outputCard is Card.Dmps3DigitalMixOutput) { if (number == (uint)CrestronControlSystem.eDmps34K250COutputs.Mix1 @@ -776,10 +793,9 @@ namespace PepperDash.Essentials.DM || number == (uint)CrestronControlSystem.eDmps34K300COutputs.Mix2 || number == (uint)CrestronControlSystem.eDmps34K350COutputs.Mix2) AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString()); - } - else if (outputCard is Card.Dmps3AecOutput) - { - AddAudioOnlyOutputPort(number, "Aec"); + + var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number % 2 + 1), string.Format("Digital Audio Output {0}", number % 2 + 1), outputCard as Card.Dmps3DigitalMixOutput); + DeviceManager.AddDevice(audioOutput); } else { From b26e1b97aa35f32ecc1cd2325f38b58a75e1b3e5 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:23:51 -0400 Subject: [PATCH 04/30] Removes redundant check for DMPS-4K type. Property exists elsewhere --- .../Devices/DeviceManager.cs | 12 +++++++++++ .../Chassis/DmpsRoutingController.cs | 20 +++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs index df864550..57bf2287 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs @@ -14,6 +14,7 @@ namespace PepperDash.Essentials.Core public static class DeviceManager { public static event EventHandler AllDevicesActivated; + public static event EventHandler AllDevicesRegistered; private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection(); private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true); @@ -57,6 +58,8 @@ namespace PepperDash.Essentials.Core { try { + OnAllDevicesRegistered(); + DeviceCriticalSection.Enter(); AddDeviceEnabled = false; // PreActivate all devices @@ -129,6 +132,15 @@ namespace PepperDash.Essentials.Core } } + private static void OnAllDevicesRegistered() + { + var handler = AllDevicesRegistered; + if (handler != null) + { + handler(null, new EventArgs()); + } + } + /// /// Calls activate on all Device class items /// diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 22dfc195..5c03e8e9 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -26,13 +26,10 @@ namespace PepperDash.Essentials.DM public CrestronControlSystem Dmps { get; set; } public ISystemControl SystemControl { get; private set; } public bool? EnableRouting { get; private set; } - - //Check if DMPS is a DMPS3-4K type for endpoint creation - public bool Dmps4kType { get; private set; } //IroutingNumericEvent public event EventHandler NumericSwitchChange; - + //Feedback for DMPS System Control public BoolFeedback SystemPowerOnFeedback { get; private set; } public BoolFeedback SystemPowerOffFeedback { get; private set; } @@ -123,14 +120,13 @@ namespace PepperDash.Essentials.DM /// public DmpsRoutingController(string key, string name, ISystemControl systemControl) : base(key, name) - { + { Dmps = Global.ControlSystem; - + switch (systemControl.SystemControlType) { case eSystemControlType.Dmps34K150CSystemControl: SystemControl = systemControl as Dmps34K150CSystemControl; - Dmps4kType = true; SystemPowerOnFeedback = new BoolFeedback(() => { return true; }); SystemPowerOffFeedback = new BoolFeedback(() => { return false; }); break; @@ -139,13 +135,11 @@ namespace PepperDash.Essentials.DM case eSystemControlType.Dmps34K300CSystemControl: case eSystemControlType.Dmps34K350CSystemControl: SystemControl = systemControl as Dmps34K300CSystemControl; - Dmps4kType = true; SystemPowerOnFeedback = new BoolFeedback(() => { return true; }); SystemPowerOffFeedback = new BoolFeedback(() => { return false; }); break; default: SystemControl = systemControl as Dmps3SystemControl; - Dmps4kType = false; SystemPowerOnFeedback = new BoolFeedback(() => { return ((Dmps3SystemControl)SystemControl).SystemPowerOnFeedBack.BoolValue; @@ -156,7 +150,7 @@ namespace PepperDash.Essentials.DM }); break; } - Debug.Console(1, this, "DMPS Type = {0}, 4K Type = {1}", systemControl.SystemControlType, Dmps4kType); + Debug.Console(1, this, "DMPS Type = {0}, 4K Type = {1}", systemControl.SystemControlType, Global.ControlSystemIsDmps4kType); InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); @@ -406,7 +400,7 @@ namespace PepperDash.Essentials.DM private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) { - if (Dmps4kType) + if (Global.ControlSystemIsDmps4kType) { //DMPS-4K audio inputs 1-5 are aux inputs for (uint i = 1; i <= 5; i++) @@ -427,12 +421,12 @@ namespace PepperDash.Essentials.DM trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); } - if (InputNameFeedbacks.ContainsKey(ioSlot) && InputNameFeedbacks[ioSlot] != null) + if (InputNameFeedbacks.ContainsKey(ioSlot) && InputNameFeedbacks[ioSlot] != null) { InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]); - if (Dmps4kType) + if (Global.ControlSystemIsDmps4kType) { //DMPS-4K Audio Inputs are offset by 5 InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin + 5]); From 03e4c913ac5824ef839a90a54ca0a09de11a38a9 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:24:19 -0400 Subject: [PATCH 05/30] Adds HD-MD-8xn switcher type support --- .../Chassis/HdMd8xNController.cs | 516 ++++++++++++++++++ 1 file changed, 516 insertions(+) create mode 100644 essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs new file mode 100644 index 00000000..00e3b974 --- /dev/null +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs @@ -0,0 +1,516 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.DM; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.DM.Config; +using Crestron.SimplSharpPro.DM.Cards; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; + + +namespace PepperDash.Essentials.DM.Chassis +{ + [Description("Wrapper class for all HdMd8xN switchers")] + public class HdMd8xNController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback + { + private HdMd8xN _Chassis; + + public event EventHandler NumericSwitchChange; + + public Dictionary InputNames { get; set; } + public Dictionary OutputNames { get; set; } + + public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection OutputPorts { get; private set; } + + public FeedbackCollection VideoInputSyncFeedbacks { get; private set; } + public FeedbackCollection VideoOutputRouteFeedbacks { get; private set; } + public FeedbackCollection AudioOutputRouteFeedbacks { get; private set; } + public FeedbackCollection InputNameFeedbacks { get; private set; } + public FeedbackCollection OutputNameFeedbacks { get; private set; } + public FeedbackCollection OutputVideoRouteNameFeedbacks { get; private set; } + public FeedbackCollection OutputAudioRouteNameFeedbacks { get; private set; } + public StringFeedback DeviceNameFeedback { get; private set; } + + #region Constructor + + public HdMd8xNController(string key, string name, HdMd8xN chassis, + DMChassisPropertiesConfig props) + : base(key, name, chassis) + { + _Chassis = chassis; + Name = name; + _Chassis.EnableAudioBreakaway.BoolValue = true; + + if (props == null) + { + Debug.Console(1, this, "HdMd8xNController properties are null, failed to build the device"); + return; + } + + InputNames = new Dictionary(); + if (props.InputNames != null) + { + InputNames = props.InputNames; + } + OutputNames = new Dictionary(); + if (props.OutputNames != null) + { + OutputNames = props.OutputNames; + } + + DeviceNameFeedback = new StringFeedback(()=> Name); + + VideoInputSyncFeedbacks = new FeedbackCollection(); + VideoOutputRouteFeedbacks = new FeedbackCollection(); + AudioOutputRouteFeedbacks = new FeedbackCollection(); + InputNameFeedbacks = new FeedbackCollection(); + OutputNameFeedbacks = new FeedbackCollection(); + OutputVideoRouteNameFeedbacks = new FeedbackCollection(); + OutputAudioRouteNameFeedbacks = new FeedbackCollection(); + + InputPorts = new RoutingPortCollection(); + OutputPorts = new RoutingPortCollection(); + + //Inputs - should always be 8 audio/video inputs + for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) + { + try + { + var index = i; + if (!InputNames.ContainsKey(index)) + { + InputNames.Add(index, string.Format("Input{0}", index)); + } + string inputName = InputNames[index]; + _Chassis.Inputs[index].Name.StringValue = inputName; + + + InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, _Chassis.Inputs[index], this) + { + FeedbackMatchObject = _Chassis.Inputs[index] + }); + + VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue)); + InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].NameFeedback.StringValue)); + } + catch (Exception ex) + { + ErrorLog.Error("Exception creating input {0} on HD-MD8xN Chassis: {1}", i, ex); + } + } + + //Outputs. Either 2 outputs (1 audio, 1 audio/video) for HD-MD8x1 or 4 outputs (2 audio, 2 audio/video) for HD-MD8x2 + for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) + { + try + { + var index = i; + if (!OutputNames.ContainsKey(index)) + { + OutputNames.Add(index, string.Format("Output{0}", index)); + } + string outputName = OutputNames[index]; + _Chassis.Outputs[index].Name.StringValue = outputName; + + OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, _Chassis.Outputs[index], this) + { + FeedbackMatchObject = _Chassis.Outputs[index] + }); + + OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].NameFeedback.StringValue)); + VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback == null ? 0 : (int)_Chassis.Outputs[index].VideoOutFeedback.Number)); + AudioOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => _Chassis.Outputs[index].AudioOutFeedback == null ? 0 : (int)_Chassis.Outputs[index].AudioOutFeedback.Number)); + OutputVideoRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback == null ? "None" : _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue)); + OutputAudioRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].AudioOutFeedback == null ? "None" : _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue)); + } + catch (Exception ex) + { + ErrorLog.Error("Exception creating output {0} on HD-MD8xN Chassis: {1}", i, ex); + } + } + + _Chassis.DMInputChange += Chassis_DMInputChange; + _Chassis.DMOutputChange += Chassis_DMOutputChange; + + AddPostActivationAction(AddFeedbackCollections); + } + #endregion + + #region Methods + + /// + /// Raise an event when the status of a switch object changes. + /// + /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType + private void OnSwitchChange(RoutingNumericEventArgs e) + { + var newEvent = NumericSwitchChange; + if (newEvent != null) newEvent(this, e); + } + + #region PostActivate + + public void AddFeedbackCollections() + { + AddFeedbackToList(DeviceNameFeedback); + AddCollectionsToList(VideoInputSyncFeedbacks); + AddCollectionsToList(VideoOutputRouteFeedbacks, AudioOutputRouteFeedbacks); + AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputVideoRouteNameFeedbacks, OutputAudioRouteNameFeedbacks); + } + + #endregion + + #region FeedbackCollection Methods + + //Add arrays of collections + public void AddCollectionsToList(params FeedbackCollection[] newFbs) + { + foreach (FeedbackCollection fbCollection in newFbs) + { + foreach (var item in newFbs) + { + AddCollectionToList(item); + } + } + } + public void AddCollectionsToList(params FeedbackCollection[] newFbs) + { + foreach (FeedbackCollection fbCollection in newFbs) + { + foreach (var item in newFbs) + { + AddCollectionToList(item); + } + } + } + + public void AddCollectionsToList(params FeedbackCollection[] newFbs) + { + foreach (FeedbackCollection fbCollection in newFbs) + { + foreach (var item in newFbs) + { + AddCollectionToList(item); + } + } + } + + //Add Collections + public void AddCollectionToList(FeedbackCollection newFbs) + { + foreach (var f in newFbs) + { + if (f == null) continue; + + AddFeedbackToList(f); + } + } + + public void AddCollectionToList(FeedbackCollection newFbs) + { + foreach (var f in newFbs) + { + if (f == null) continue; + + AddFeedbackToList(f); + } + } + + public void AddCollectionToList(FeedbackCollection newFbs) + { + foreach (var f in newFbs) + { + if (f == null) continue; + + AddFeedbackToList(f); + } + } + + //Add Individual Feedbacks + public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback newFb) + { + if (newFb == null) return; + + if (!Feedbacks.Contains(newFb)) + { + Feedbacks.Add(newFb); + } + } + + #endregion + + #region IRouting Members + + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType) + { + var input = inputSelector as DMInput; + var output = outputSelector as DMOutput; + Debug.Console(2, this, "ExecuteSwitch: input={0} output={1} sigType={2}", input, output, sigType.ToString()); + + if (output == null) + { + Debug.Console(0, this, "Unable to make switch. Output selector is not DMOutput"); + return; + } + + if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) + { + _Chassis.VideoEnter.BoolValue = true; + if (output != null) + { + output.VideoOut = input; + } + } + + if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) + { + _Chassis.AudioEnter.BoolValue = true; + if (output != null) + { + output.AudioOut = input; + } + } + } + + #endregion + + #region IRoutingNumeric Members + + public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) + { + + var input = inputSelector == 0 ? null : _Chassis.Inputs[inputSelector]; + var output = _Chassis.Outputs[outputSelector]; + + Debug.Console(2, this, "ExecuteNumericSwitch: input={0} output={1}", input, output); + + ExecuteSwitch(input, output, signalType); + } + + #endregion + + #endregion + + #region Bridge Linking + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new DmChassisControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = "DM Switcher"; + + for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) + { + var joinIndex = i - 1; + var input = i; + //Digital + VideoInputSyncFeedbacks[InputNames[input]].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + joinIndex]); + + //Serial + InputNameFeedbacks[InputNames[input]].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + joinIndex]); + } + + for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) + { + var joinIndex = i - 1; + var output = i; + //Analog + VideoOutputRouteFeedbacks[OutputNames[output]].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + joinIndex]); + trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + joinIndex, (a) => ExecuteNumericSwitch(a, (ushort)output, eRoutingSignalType.Video)); + AudioOutputRouteFeedbacks[OutputNames[output]].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + joinIndex]); + trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + joinIndex, (a) => ExecuteNumericSwitch(a, (ushort)output, eRoutingSignalType.Audio)); + + //Serial + OutputNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + joinIndex]); + OutputVideoRouteNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + joinIndex]); + OutputAudioRouteNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + joinIndex]); + } + + _Chassis.OnlineStatusChange += Chassis_OnlineStatusChange; + + trilist.OnlineStatusChange += (d, args) => + { + if (!args.DeviceOnLine) return; + }; + } + + + #endregion + + #region Events + + void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args) + { + IsOnline.FireUpdate(); + + if (!args.DeviceOnLine) return; + + foreach (var feedback in Feedbacks) + { + feedback.FireUpdate(); + } + } + + void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args) + { + switch (args.EventId) + { + case DMOutputEventIds.VideoOutEventId: + { + var output = args.Number; + var inputNumber = _Chassis.Outputs[output].VideoOutFeedback == null ? 0 : _Chassis.Outputs[output].VideoOutFeedback.Number; + + var outputName = OutputNames[output]; + + var feedback = VideoOutputRouteFeedbacks[outputName]; + + if (feedback == null) + { + return; + } + var inPort = InputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.Outputs[output].VideoOutFeedback); + var outPort = OutputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.Outputs[output]); + + feedback.FireUpdate(); + OnSwitchChange(new RoutingNumericEventArgs(output, inputNumber, outPort, inPort, eRoutingSignalType.Video)); + break; + } + case DMOutputEventIds.AudioOutEventId: + { + var output = args.Number; + var inputNumber = _Chassis.Outputs[output].AudioOutFeedback == null ? 0 : _Chassis.Outputs[output].AudioOutFeedback.Number; + + var outputName = OutputNames[output]; + + var feedback = AudioOutputRouteFeedbacks[outputName]; + + if (feedback == null) + { + return; + } + var inPort = InputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.Outputs[output].AudioOutFeedback); + var outPort = OutputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.Outputs[output]); + + feedback.FireUpdate(); + OnSwitchChange(new RoutingNumericEventArgs(output, inputNumber, outPort, inPort, eRoutingSignalType.Audio)); + break; + } + case DMOutputEventIds.OutputNameEventId: + case DMOutputEventIds.NameFeedbackEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating name feedbacks.", args.EventId); + Debug.Console(1, this, "Output {0} Name {1}", args.Number, + _Chassis.Outputs[args.Number].NameFeedback.StringValue); + foreach (var item in OutputNameFeedbacks) + { + item.FireUpdate(); + } + break; + } + default: + { + Debug.Console(1, this, "Unhandled DM Output Event ID {0}", args.EventId); + break; + } + } + } + + void Chassis_DMInputChange(Switch device, DMInputEventArgs args) + { + switch (args.EventId) + { + case DMInputEventIds.VideoDetectedEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", args.EventId); + 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.", args.EventId); + Debug.Console(1, this, "Input {0} Name {1}", args.Number, + _Chassis.Inputs[args.Number].NameFeedback.StringValue); + foreach (var item in InputNameFeedbacks) + { + item.FireUpdate(); + } + break; + } + default: + { + Debug.Console(1, this, "Unhandled DM Input Event ID {0}", args.EventId); + break; + } + } + } + + #endregion + + #region Factory + + public class HdMd8xNControllerFactory : EssentialsDeviceFactory + { + public HdMd8xNControllerFactory() + { + TypeNames = new List() { "hdmd8x2", "hdmd8x1" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new HD-MD-8xN Device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + var type = dc.Type.ToLower(); + var control = props.Control; + var ipid = control.IpIdInt; + + switch (type) + { + case ("hdmd8x2"): + return new HdMd8xNController(dc.Key, dc.Name, new HdMd8x2(ipid, Global.ControlSystem), props); + case ("hdmd8x1"): + return new HdMd8xNController(dc.Key, dc.Name, new HdMd8x1(ipid, Global.ControlSystem), props); + default: + return null; + } + } + } + + #endregion + + + + } +} \ No newline at end of file From 50e9a7935fa4de917a26dd67dabcc8cb50a10c3f Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:25:06 -0400 Subject: [PATCH 06/30] Adds HD-MD-8xn switcher type support --- .../Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj | 1 + 1 file changed, 1 insertion(+) 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 cef61b1a..ea3dbd5d 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -100,6 +100,7 @@ + From 1a5d4896e168f6ee93e70adeb5eced1d3174cde8 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 14 Jun 2022 10:43:29 -0400 Subject: [PATCH 07/30] Fixes online feedback for DM endpoints that are attached to a 3 series DM chassis or a DMPS-4K unit. --- .../Crestron/CrestronGenericBaseDevice.cs | 18 ++- .../DmpsInternalVirtualDmTxController.cs | 25 ++-- .../Chassis/DmpsRoutingController.cs | 12 ++ .../Chassis/HdMd8xNController.cs | 2 +- .../Endpoints/Receivers/DmRmcHelper.cs | 120 +++++++++++------- .../Endpoints/Transmitters/DmTxHelpers.cs | 41 +++++- 6 files changed, 155 insertions(+), 63 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs index b7534087..f4d13d4e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs @@ -20,7 +20,7 @@ namespace PepperDash.Essentials.Core /// public FeedbackCollection Feedbacks { get; private set; } - public BoolFeedback IsOnline { get; private set; } + public BoolFeedback IsOnline { get; set; } public BoolFeedback IsRegistered { get; private set; } public StringFeedback IpConnectionsText { get; private set; } @@ -73,11 +73,14 @@ namespace PepperDash.Essentials.Core { //Debug.Console(1, this, " Does not require registration. Skipping"); - var response = Hardware.RegisterWithLogging(Key); - if (response != eDeviceRegistrationUnRegistrationResponse.Success) + if (Hardware.Registerable && !Hardware.Registered) { - //Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response); - return false; + var response = Hardware.RegisterWithLogging(Key); + if (response != eDeviceRegistrationUnRegistrationResponse.Success) + { + //Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response); + return false; + } } IsRegistered.FireUpdate(); @@ -86,7 +89,10 @@ namespace PepperDash.Essentials.Core { AddPostActivationAction(() => { - var response = Hardware.RegisterWithLogging(Key); + if (Hardware.Registerable && !Hardware.Registered) + { + var response = Hardware.RegisterWithLogging(Key); + } IsRegistered.FireUpdate(); }); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs index 75ba7e29..c9c2f261 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsInternalVirtualDmTxController.cs @@ -47,16 +47,23 @@ namespace PepperDash.Essentials.DM { get { - if (InputCard.VideoSourceFeedback != eDmps3InputVideoSource.Auto) - return InputCard.VideoSourceFeedback; - else // auto + try { - if (InputCard.HdmiInputPort.SyncDetectedFeedback.BoolValue) - return eDmps3InputVideoSource.Hdmi; - else if (InputCard.VgaInputPort.SyncDetectedFeedback.BoolValue) - return eDmps3InputVideoSource.Vga; - else - return eDmps3InputVideoSource.Bnc; + if (InputCard.VideoSourceFeedback != eDmps3InputVideoSource.Auto) + return InputCard.VideoSourceFeedback; + else // auto + { + if (InputCard.HdmiInputPort.SyncDetectedFeedback.BoolValue) + return eDmps3InputVideoSource.Hdmi; + else if (InputCard.VgaInputPort.SyncDetectedFeedback.BoolValue) + return eDmps3InputVideoSource.Vga; + else + return eDmps3InputVideoSource.Bnc; + } + } + catch + { + return eDmps3InputVideoSource.Bnc; } } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 5c03e8e9..38a0aed9 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -861,6 +861,7 @@ namespace PepperDash.Essentials.DM void Dmps_DMInputChange(Switch device, DMInputEventArgs args) { + Debug.Console(2, this, "DMInputChange Input: {0} EventId: {1}", args.Number, args.EventId.ToString()); try { switch (args.EventId) @@ -871,6 +872,12 @@ namespace PepperDash.Essentials.DM InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); break; } + case (DMInputEventIds.EndpointOnlineEventId): + { + Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); + InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); + break; + } case (DMInputEventIds.VideoDetectedEventId): { Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number); @@ -916,6 +923,11 @@ namespace PepperDash.Essentials.DM { OutputEndpointOnlineFeedbacks[output].FireUpdate(); } + else if (args.EventId == DMOutputEventIds.EndpointOnlineEventId + && OutputEndpointOnlineFeedbacks.ContainsKey(output)) + { + OutputEndpointOnlineFeedbacks[output].FireUpdate(); + } else if (args.EventId == DMOutputEventIds.VideoOutEventId) { if (outputCard != null && outputCard.VideoOutFeedback != null) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs index 00e3b974..2343f65a 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMd8xNController.cs @@ -323,7 +323,7 @@ namespace PepperDash.Essentials.DM.Chassis IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - trilist.StringInput[joinMap.Name.JoinNumber].StringValue = "DM Switcher"; + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) { diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs index a9282693..ced21918 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs @@ -30,14 +30,15 @@ namespace PepperDash.Essentials.DM : base(key, name, device) { _rmc = device; + // if wired to a chassis, skip registration step in base class PreventRegistration = _rmc.DMOutput != null; AddToFeedbackList(VideoOutputResolutionFeedback, EdidManufacturerFeedback, EdidSerialNumberFeedback, EdidNameFeedback, EdidPreferredTimingFeedback); - + DeviceInfo = new DeviceInfo(); - _rmc.OnlineStatusChange += (currentDevice, args) => { if (args.DeviceOnLine) UpdateDeviceInfo(); }; + IsOnline.OutputChange += (currentDevice, args) => { if (args.BoolValue) UpdateDeviceInfo(); }; } protected void LinkDmRmcToApi(DmRmcControllerBase rmc, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) @@ -60,7 +61,7 @@ namespace PepperDash.Essentials.DM Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - rmc.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); trilist.StringInput[joinMap.Name.JoinNumber].StringValue = rmc.Name; if (rmc.VideoOutputResolutionFeedback != null) rmc.VideoOutputResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentOutputResolution.JoinNumber]); @@ -330,53 +331,84 @@ namespace PepperDash.Essentials.DM var parentDev = DeviceManager.GetDeviceForKey(pKey); if (parentDev is DmpsRoutingController) { - if ((parentDev as DmpsRoutingController).Dmps4kType) + var dmps = parentDev as DmpsRoutingController; + //Check that the input is within range of this chassis' possible inputs + var num = props.ParentOutputNumber; + Debug.Console(1, "Creating DMPS device '{0}'. Output number '{1}'.", key, num); + if (num <= 0 || num > dmps.Dmps.SwitcherOutputs.Count) { - return GetDmRmcControllerForDmps4k(key, name, typeName, parentDev as DmpsRoutingController, props.ParentOutputNumber); + Debug.Console(0, "Cannot create DMPS device '{0}'. Output number '{1}' is out of range", + key, num); + return null; } - else + // Must use different constructor for DMPS4K types. No IPID + if (Global.ControlSystemIsDmps4kType) { - return GetDmRmcControllerForDmps(key, name, typeName, ipid, parentDev as DmpsRoutingController, props.ParentOutputNumber); + var rmc = GetDmRmcControllerForDmps4k(key, name, typeName, dmps, props.ParentOutputNumber); + Debug.Console(0, "DM endpoint output {0} is for Dmps4k, changing online feedback to chassis", num); + rmc.IsOnline = dmps.OutputEndpointOnlineFeedbacks[num]; + rmc.IsOnline.OutputChange += (currentDevice, args) => + { + foreach (var feedback in rmc.Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } + }; + return rmc; } + return GetDmRmcControllerForDmps(key, name, typeName, ipid, dmps, props.ParentOutputNumber); } - if (!(parentDev is IDmSwitch)) - { - Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a DM Chassis.", - key, pKey); - return null; - } + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + var chassis = controller.Chassis; + var num = props.ParentOutputNumber; + Debug.Console(1, "Creating DM Chassis device '{0}'. Output number '{1}'.", key, num); - var chassis = (parentDev as IDmSwitch).Chassis; - var num = props.ParentOutputNumber; - - if (num <= 0 || num > chassis.NumberOfOutputs) - { - Debug.Console(0, "Cannot create DM device '{0}'. Output number '{1}' is out of range", - key, num); - return null; - } - - var controller = parentDev as IDmSwitch; - controller.RxDictionary.Add(num, key); - // Catch constructor failures, mainly dues to IPID - try - { - // Must use different constructor for CPU3 chassis types. No IPID - if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || - chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || - chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) - { - return GetDmRmcControllerForCpu3Chassis(key, name, typeName, chassis, num, parentDev); - } - - return GetDmRmcControllerForCpu2Chassis(key, name, typeName, ipid, chassis, num, parentDev); - } - catch (Exception e) - { - Debug.Console(0, "[{0}] WARNING: Cannot create DM-RMC device: {1}", key, e.Message); - return null; - } + if (num <= 0 || num > chassis.NumberOfOutputs) + { + Debug.Console(0, "Cannot create DM device '{0}'. Output number '{1}' is out of range", + key, num); + return null; + } + controller.RxDictionary.Add(num, key); + // Catch constructor failures, mainly dues to IPID + try + { + // Must use different constructor for CPU3 chassis types. No IPID + if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || + chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || + chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || + chassis is DmMd128x128 || chassis is DmMd64x64) + { + var rmc = GetDmRmcControllerForCpu3Chassis(key, name, typeName, chassis, num, parentDev); + Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); + rmc.IsOnline = controller.OutputEndpointOnlineFeedbacks[num]; + rmc.IsOnline.OutputChange += (currentDevice, args) => + { + foreach (var feedback in rmc.Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } + }; + return rmc; + } + return GetDmRmcControllerForCpu2Chassis(key, name, typeName, ipid, chassis, num, parentDev); + } + catch (Exception e) + { + Debug.Console(0, "[{0}] WARNING: Cannot create DM-RMC device: {1}", key, e.Message); + return null; + } + } + else + { + Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a DM Chassis or DMPS.", + key, pKey); + return null; + } } private static CrestronGenericBaseDevice GetDmRmcControllerForCpu2Chassis(string key, string name, string typeName, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs index 5eb2d7b5..4883849e 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs @@ -137,7 +137,7 @@ namespace PepperDash.Essentials.DM try { // Must use different constructor for CPU3 or DMPS3-4K types. No IPID - if (isCpu3 || Global.ControlSystemIsDmps4kType) + if (isCpu3 || (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType)) { if (typeName.StartsWith("dmtx200")) return new DmTx200Controller(key, name, new DmTx200C2G(dmInput)); @@ -145,7 +145,7 @@ namespace PepperDash.Essentials.DM return new DmTx201CController(key, name, new DmTx201C(dmInput)); if (typeName.StartsWith("dmtx201s")) return new DmTx201SController(key, name, new DmTx201S(dmInput)); - if (typeName.StartsWith("dmtx4k100")) + if (typeName.StartsWith("dmtx4k100")) return new DmTx4k100Controller(key, name, new DmTx4K100C1G(dmInput)); if (typeName.StartsWith("dmtx4kz100")) return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(dmInput)); @@ -153,7 +153,7 @@ namespace PepperDash.Essentials.DM return new DmTx4k202CController(key, name, new DmTx4k202C(dmInput)); if (typeName.StartsWith("dmtx4kz202")) return new DmTx4kz202CController(key, name, new DmTx4kz202C(dmInput)); - if (typeName.StartsWith("dmtx4k302")) + if (typeName.StartsWith("dmtx4k302")) return new DmTx4k302CController(key, name, new DmTx4k302C(dmInput)); if (typeName.StartsWith("dmtx4kz302")) return new DmTx4kz302CController(key, name, new DmTx4kz302C(dmInput)); @@ -228,6 +228,41 @@ namespace PepperDash.Essentials.DM } AddToFeedbackList(ActiveVideoInputFeedback); + + var parentDev = DeviceManager.GetDeviceForKey(key); + var num = hardware.DMInput.Number; + + //If Dmps4K, change online feedback to chassis, tx feedback does not work + if (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType) + { + var dmps = parentDev as DmpsRoutingController; + Debug.Console(0, "DM endpoint input {0} is for Dmps4k, changing online feedback to chassis", num); + IsOnline = dmps.InputEndpointOnlineFeedbacks[num]; + } + //If Cpu3 Chassis, change online feedback to chassis, tx feedback does not work + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + var chassis = controller.Chassis; + + if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || + chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || + chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || + chassis is DmMd128x128 || chassis is DmMd64x64) + { + Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); + IsOnline = controller.InputEndpointOnlineFeedbacks[num]; + } + } + + IsOnline.OutputChange += (currentDevice, args) => + { + foreach (var feedback in Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } + }; } protected DmTxControllerBase(string key, string name, DmHDBasedTEndPoint hardware) : base(key, name, hardware) From 6dbdd0587d22431cef4992ddea9c76d4a81ae6bf Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 15 Jun 2022 08:49:52 -0400 Subject: [PATCH 08/30] Reworks audio routing on DMPS-4K units. --- .../Chassis/DmpsDigitalOutputController.cs | 171 +++++++++ .../Chassis/DmpsMicrophoneController.cs | 3 + .../Chassis/DmpsRoutingController.cs | 344 ++++++++++++++---- .../PepperDash_Essentials_DM.csproj | 1 + 4 files changed, 447 insertions(+), 72 deletions(-) create mode 100644 essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs new file mode 100644 index 00000000..49b5c1c5 --- /dev/null +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.DM; +using Crestron.SimplSharpPro.DM.Cards; + +using PepperDash.Core; +using PepperDash.Essentials.Core; + + +namespace PepperDash.Essentials.DM +{ + /// + /// + /// + public class DmpsDigitalOutputController : Device, IRoutingNumericWithFeedback, IHasFeedback + { + public Card.Dmps3OutputBase OutputCard { get; protected set; } + + public RoutingInputPort None { get; protected set; } + public RoutingInputPort DigitalMix1 { get; protected set; } + public RoutingInputPort DigitalMix2 { get; protected set; } + public RoutingInputPort AudioFollowsVideo { get; protected set; } + + public RoutingOutputPort DigitalAudioOut { get; protected set; } + + public IntFeedback AudioSourceNumericFeedback { get; protected set; } + + /// + /// Returns a list containing the Outputs that we want to expose. + /// + public FeedbackCollection Feedbacks { get; private set; } + + public virtual RoutingPortCollection InputPorts + { + get + { + return new RoutingPortCollection + { + None, + DigitalMix1, + DigitalMix2, + AudioFollowsVideo + }; + } + } + + public RoutingPortCollection OutputPorts + { + get + { + return new RoutingPortCollection { DigitalAudioOut }; + } + } + + public DmpsDigitalOutputController(string key, string name, Card.Dmps3OutputBase outputCard) + : base(key, name) + { + Feedbacks = new FeedbackCollection(); + OutputCard = outputCard; + + if (outputCard is Card.Dmps3DmOutputBackend) + { + AudioSourceNumericFeedback = new IntFeedback(() => + { + return (int)(outputCard as Card.Dmps3DmOutputBackend).AudioOutSourceDeviceFeedback; + }); + DigitalAudioOut = new RoutingOutputPort(DmPortName.DmOut + OutputCard.Number, eRoutingSignalType.Audio, eRoutingPortConnectionType.DmCat, null, this); + } + + else if (outputCard is Card.Dmps3HdmiOutputBackend) + { + AudioSourceNumericFeedback = new IntFeedback(() => + { + return (int)(outputCard as Card.Dmps3HdmiOutputBackend).AudioOutSourceDeviceFeedback; + }); + DigitalAudioOut = new RoutingOutputPort(DmPortName.HdmiOut + OutputCard.Number, eRoutingSignalType.Audio, eRoutingPortConnectionType.Hdmi, null, this); + } + else + { + return; + } + + None = new RoutingInputPort("None", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + eDmps34KAudioOutSourceDevice.NoRoute, this); + DigitalMix1 = new RoutingInputPort("DigitalMix1", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + eDmps34KAudioOutSourceDevice.DigitalMixer1, this); + DigitalMix2 = new RoutingInputPort("DigitalMix2", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + eDmps34KAudioOutSourceDevice.DigitalMixer2, this); + AudioFollowsVideo = new RoutingInputPort("AudioFollowsVideo", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio, + eDmps34KAudioOutSourceDevice.AudioFollowsVideo, this); + + AddToFeedbackList(AudioSourceNumericFeedback); + } + + /// + /// Adds feedback(s) to the list + /// + /// + public void AddToFeedbackList(params Feedback[] newFbs) + { + foreach (var f in newFbs) + { + if (f != null) + { + if (!Feedbacks.Contains(f)) + { + Feedbacks.Add(f); + } + } + } + } + + public virtual void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type) + { + Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input); + + switch (input) + { + case 0: + { + ExecuteSwitch(None.Selector, null, type); + break; + } + case 1: + { + ExecuteSwitch(DigitalMix1.Selector, null, type); + break; + } + case 2: + { + ExecuteSwitch(DigitalMix2.Selector, null, type); + break; + } + case 3: + { + ExecuteSwitch(AudioFollowsVideo.Selector, null, type); + break; + } + } + + } + + #region IRouting Members + + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) + { + if ((signalType | eRoutingSignalType.Audio) == eRoutingSignalType.Audio) + { + if (OutputCard is Card.Dmps3DmOutputBackend) + { + (OutputCard as Card.Dmps3DmOutputBackend).AudioOutSourceDevice = (eDmps34KAudioOutSourceDevice)inputSelector; + } + else if (OutputCard is Card.Dmps3HdmiOutputBackend) + { + (OutputCard as Card.Dmps3HdmiOutputBackend).AudioOutSourceDevice = (eDmps34KAudioOutSourceDevice)inputSelector; + } + } + } + + #endregion + + #region IRoutingFeedback Members + + public event EventHandler NumericSwitchChange; + + #endregion + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsMicrophoneController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsMicrophoneController.cs index 30b2cfab..29dc0693 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsMicrophoneController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsMicrophoneController.cs @@ -38,6 +38,9 @@ namespace PepperDash.Essentials.DM void Dmps_MicrophoneChange(MicrophoneBase mic, GenericEventArgs args) { + if (args.EventId == MicrophoneEventIds.VuFeedBackEventId) + return; + Debug.Console(2, "Dmps Microphone Controller Index: {0} EventId: {1}", mic.ID, args.EventId.ToString()); if(Mics.ContainsKey(mic.ID)) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 38a0aed9..55c49a96 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -59,6 +59,7 @@ namespace PepperDash.Essentials.DM public Dictionary InputNames { get; set; } public Dictionary OutputNames { get; set; } public Dictionary VolumeControls { get; private set; } + public Dictionary DigitalAudioOutputs { get; private set; } public DmpsMicrophoneController Microphones { get; private set; } public const int RouteOffTime = 500; @@ -155,6 +156,7 @@ namespace PepperDash.Essentials.DM InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); VolumeControls = new Dictionary(); + DigitalAudioOutputs = new Dictionary(); TxDictionary = new Dictionary(); RxDictionary = new Dictionary(); @@ -246,13 +248,15 @@ namespace PepperDash.Essentials.DM { return; } - foreach (var kvp in OutputNames) { var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput); - if (output != null && output.Name.Type != eSigType.NA) + if (output != null) { - output.Name.StringValue = kvp.Value; + if (output.Name.Supported && kvp.Value.Length > 0) + { + output.Name.StringValue = kvp.Value; + } } } } @@ -266,9 +270,12 @@ namespace PepperDash.Essentials.DM foreach (var kvp in InputNames) { var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput); - if (input != null && input.Name.Type != eSigType.NA) + if (input != null) { - input.Name.StringValue = kvp.Value; + if (input.Name.Supported && kvp.Value.Length > 0) + { + input.Name.StringValue = kvp.Value; + } } } } @@ -376,9 +383,20 @@ namespace PepperDash.Essentials.DM } if (OutputNameFeedbacks[ioSlot] != null) { - OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); - OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputVideoNames.JoinNumber + ioSlotJoin]); - OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputAudioNames.JoinNumber + ioSlotJoin]); + if (Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmOutput || + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmOutputBackend || + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutput || + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutputBackend) + { + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputVideoNames.JoinNumber + ioSlotJoin]); + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputAudioNames.JoinNumber + ioSlotJoin]); + } + else + { + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputAudioNames.JoinNumber + ioSlotJoin]); + } } if (OutputVideoRouteNameFeedbacks[ioSlot] != null) { @@ -402,11 +420,15 @@ namespace PepperDash.Essentials.DM { if (Global.ControlSystemIsDmps4kType) { - //DMPS-4K audio inputs 1-5 are aux inputs - for (uint i = 1; i <= 5; i++) + //DMPS-4K audio inputs 1-5 are aux inputs, add them after regular dm cards + for (ushort i = 1; i <= 5; i++) { - trilist.StringInput[joinMap.InputAudioNames.JoinNumber + i - 1].StringValue = String.Format("Aux Input {0}", i); + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + i - 1 + (ushort)Dmps.SwitcherInputs.Count].StringValue = String.Format("Aux Input {0}", i); } + + //Add DMPS-4K mixer input names to end of inputs + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 5].StringValue = "Digital Mixer 1"; + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 6].StringValue = "Digital Mixer 2"; } for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++) { @@ -425,16 +447,7 @@ namespace PepperDash.Essentials.DM { InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]); - - if (Global.ControlSystemIsDmps4kType) - { - //DMPS-4K Audio Inputs are offset by 5 - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin + 5]); - } - else - { - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]); - } + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]); } trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s => @@ -496,7 +509,7 @@ namespace PepperDash.Essentials.DM }); AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() => { - try + if (!Global.ControlSystemIsDmps4kType) { if (outputCard.AudioOutFeedback != null) { @@ -504,15 +517,58 @@ namespace PepperDash.Essentials.DM } return 0; } - catch (NotSupportedException) + else { - return (ushort)outputCard.AudioOutSourceFeedback; + + if (outputCard is Card.Dmps3DmOutputBackend || outputCard is Card.Dmps3HdmiOutputBackend) + { + //Special cases for DMPS-4K digital audio output + if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 0) + return 0; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 1) + return (ushort)Dmps.SwitcherInputs.Count + 6; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 2) + return (ushort)Dmps.SwitcherInputs.Count + 7; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 3) + return (ushort)outputCard.VideoOutFeedback.Number; + else + return 0; + } + else if (outputCard.AudioOutSourceFeedback == eDmps34KAudioOutSource.NoRoute) + { + //Fixes for weird audio indexing on DMPS3-4K + return 0; + } + else if (outputCard.AudioOutSourceFeedback == eDmps34KAudioOutSource.AirMedia8) + { + //Fixes for weird audio indexing on DMPS3-4K + return 8; + } + else if (outputCard.AudioOutSourceFeedback == eDmps34KAudioOutSource.AirMedia9) + { + //Fixes for weird audio indexing on DMPS3-4K + return 9; + } + else if ((ushort)outputCard.AudioOutSourceFeedback <= 5) + { + //Move analog inputs to after regular dm cards + return (ushort)outputCard.AudioOutSourceFeedback + (ushort)Dmps.SwitcherInputs.Count; + } + else + { + //Fixes for weird audio indexing on DMPS3-4K + return (ushort)outputCard.AudioOutSourceFeedback - 5; + } } }); OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => { - if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) + if(OutputNames.ContainsKey(outputCard.Number)) + { + return OutputNames[outputCard.Number]; + } + else if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) { Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue); return outputCard.NameFeedback.StringValue; @@ -530,9 +586,33 @@ namespace PepperDash.Essentials.DM }); OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => { - if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) + if (!Global.ControlSystemIsDmps4kType) { - return outputCard.AudioOutFeedback.NameFeedback.StringValue; + if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) + { + return outputCard.AudioOutFeedback.NameFeedback.StringValue; + } + } + else + { + if (outputCard is Card.Dmps3DmOutputBackend || outputCard is Card.Dmps3HdmiOutputBackend) + { + //Special cases for DMPS-4K digital audio output + if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 0) + return NoRouteText; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 1) + return "Digital Mix 1"; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 2) + return "Digital Mix 2"; + else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 3) + return outputCard.VideoOutFeedback.NameFeedback.StringValue; + else + return NoRouteText; + } + else + { + return outputCard.AudioOutSourceFeedback.ToString(); + } } return NoRouteText; }); @@ -570,13 +650,15 @@ namespace PepperDash.Essentials.DM InputNameFeedbacks[inputCard.Number] = new StringFeedback(() => { - if (inputCard.NameFeedback != null && inputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue)) + if (InputNames.ContainsKey(inputCard.Number)) + { + return InputNames[inputCard.Number]; + } + else if (inputCard.NameFeedback != null && inputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue)) { Debug.Console(2, this, "Input Card {0} Name: {1}", inputCard.Number, inputCard.NameFeedback.StringValue); return inputCard.NameFeedback.StringValue; } - - Debug.Console(2, this, "Input Card {0} Name is null", inputCard.Number); return ""; }); @@ -705,10 +787,11 @@ namespace PepperDash.Essentials.DM else if (outputCard is Card.Dmps3HdmiOutputBackend) { var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend; - var cecPort = hdmiOutputCard.HdmiOutputPort; - AddHdmiOutputPort(number, cecPort); + var audioOutput = new DmpsDigitalOutputController(string.Format("processor-avRouting-HdmiAudioOut{0}", number), string.Format("Hdmi Audio Output {0} Router", number), hdmiOutputCard); + DigitalAudioOutputs.Add(number, audioOutput); + DeviceManager.AddDevice(audioOutput); } else if (outputCard is Card.Dmps3DmOutput) { @@ -720,6 +803,9 @@ namespace PepperDash.Essentials.DM else if (outputCard is Card.Dmps3DmOutputBackend) { AddDmOutputPort(number); + var audioOutput = new DmpsDigitalOutputController(string.Format("processor-avRouting-DmAudioOut{0}", number), string.Format("Dm Audio Output {0} Router", number), outputCard as Card.Dmps3DmOutputBackend); + DigitalAudioOutputs.Add(number, audioOutput); + DeviceManager.AddDevice(audioOutput); } else if (outputCard is Card.Dmps3ProgramOutput) { @@ -737,7 +823,7 @@ namespace PepperDash.Essentials.DM { AddAudioOnlyOutputPort(number, "Aux1"); - var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux1Output); + var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Aux1 Audio Output", outputCard as Card.Dmps3Aux1Output); DeviceManager.AddDevice(aux1Output); } @@ -746,7 +832,7 @@ namespace PepperDash.Essentials.DM { AddAudioOnlyOutputPort(number, "Aux2"); - var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux2Output); + var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Aux2 Audio Output", outputCard as Card.Dmps3Aux2Output); DeviceManager.AddDevice(aux2Output); } @@ -788,7 +874,7 @@ namespace PepperDash.Essentials.DM || number == (uint)CrestronControlSystem.eDmps34K350COutputs.Mix2) AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString()); - var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number % 2 + 1), string.Format("Digital Audio Output {0}", number % 2 + 1), outputCard as Card.Dmps3DigitalMixOutput); + var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number % 2 + 1), string.Format("Digital Audio Mix {0}", number % 2 + 1), outputCard as Card.Dmps3DigitalMixOutput); DeviceManager.AddDevice(audioOutput); } else @@ -902,14 +988,13 @@ namespace PepperDash.Essentials.DM } void Dmps_DMOutputChange(Switch device, DMOutputEventArgs args) { - Debug.Console(2, this, "DMOutputChange Output: {0} EventId: {1}", args.Number, args.EventId.ToString()); - if (args.EventId == DMOutputEventIds.OutputVuFeedBackEventId) { //Frequently called event that isn't needed return; } + Debug.Console(2, this, "DMOutputChange Output: {0} EventId: {1}", args.Number, args.EventId.ToString()); var output = args.Number; DMOutput outputCard = Dmps.SwitcherOutputs[output] as DMOutput; @@ -942,41 +1027,68 @@ namespace PepperDash.Essentials.DM { OutputVideoRouteNameFeedbacks[output].FireUpdate(); } + if (outputCard is Card.Dmps3DmOutputBackend || outputCard is Card.Dmps3HdmiOutputBackend) + { + if (AudioOutputFeedbacks.ContainsKey(output)) + { + AudioOutputFeedbacks[output].FireUpdate(); + } + if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) + { + OutputAudioRouteNameFeedbacks[output].FireUpdate(); + } + } } else if (args.EventId == DMOutputEventIds.AudioOutEventId) { - try + if (!Global.ControlSystemIsDmps4kType) { if (outputCard != null && outputCard.AudioOutFeedback != null) { Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, outputCard.AudioOutFeedback.Number, output); } - if (AudioOutputFeedbacks.ContainsKey(output)) - { - AudioOutputFeedbacks[output].FireUpdate(); - } } - catch (NotSupportedException) + else { if (outputCard != null) { - Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name, - outputCard.AudioOutSourceFeedback, output); - } - if (AudioOutputFeedbacks.ContainsKey(output)) - { - AudioOutputFeedbacks[output].FireUpdate(); + if (outputCard is Card.Dmps3DmOutputBackend || outputCard is Card.Dmps3HdmiOutputBackend) + { + DigitalAudioOutputs[output].AudioSourceNumericFeedback.FireUpdate(); + } + else + { + Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name, + outputCard.AudioOutSourceFeedback, output); + } } } + if (AudioOutputFeedbacks.ContainsKey(output)) + { + AudioOutputFeedbacks[output].FireUpdate(); + } + if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) + { + OutputAudioRouteNameFeedbacks[output].FireUpdate(); + } } else if (args.EventId == DMOutputEventIds.OutputNameEventId && OutputNameFeedbacks.ContainsKey(output)) { - Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); OutputNameFeedbacks[output].FireUpdate(); } - + else if (args.EventId == DMOutputEventIds.DigitalMixerAudioSourceFeedBackEventId) + { + if (AudioOutputFeedbacks.ContainsKey(output)) + { + AudioOutputFeedbacks[output].FireUpdate(); + } + if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) + { + OutputAudioRouteNameFeedbacks[output].FireUpdate(); + } + } } void Dmps_DMSystemChange(Switch device, DMSystemEventArgs args) @@ -1024,9 +1136,6 @@ namespace PepperDash.Essentials.DM Debug.Console(2, this, "Attempting a DM route from input {0} to output {1} {2}", inputSelector, outputSelector, sigType); - //var input = Convert.ToUInt32(inputSelector); // Cast can sometimes fail - //var output = Convert.ToUInt32(outputSelector); - var input = inputSelector as DMInput; var output = outputSelector as DMOutput; @@ -1044,7 +1153,7 @@ namespace PepperDash.Essentials.DM if (input == null || (input.Number <= Dmps.NumberOfSwitcherInputs && output.Number <= Dmps.NumberOfSwitcherOutputs && sigTypeIsUsbOrVideo) || - (input.Number <= Dmps.NumberOfSwitcherInputs + 5 && output.Number <= Dmps.NumberOfSwitcherOutputs && + (input.Number <= (Dmps.NumberOfSwitcherInputs) && output.Number <= Dmps.NumberOfSwitcherOutputs && (sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)) { // Check to see if there's an off timer waiting on this and if so, cancel @@ -1063,11 +1172,6 @@ namespace PepperDash.Essentials.DM } } - - //DMOutput dmOutputCard = output == 0 ? null : Dmps.SwitcherOutputs[output] as DMOutput; - - //if (inCard != null) - //{ // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) { @@ -1076,19 +1180,34 @@ namespace PepperDash.Essentials.DM if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) { - try + if(!Global.ControlSystemIsDmps4kType) { output.AudioOut = input; } - catch (NotSupportedException) + else { - Debug.Console(1, this, "Routing input {0} audio to output {1}", - (eDmps34KAudioOutSource) (input == null ? 0 : input.Number), - (CrestronControlSystem.eDmps34K350COutputs) output.Number); - - output.AudioOutSource = input == null - ? eDmps34KAudioOutSource.NoRoute - : (eDmps34KAudioOutSource)input.Number; + if (input == null) + { + output.AudioOutSource = eDmps34KAudioOutSource.NoRoute; + } + else if (input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaInput || input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaNoStreamingInput) + { + //Special case for weird AirMedia indexing + if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl) + output.AudioOutSource = eDmps34KAudioOutSource.AirMedia8; + else if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) + output.AudioOutSource = eDmps34KAudioOutSource.AirMedia9; + } + else if (input.Number <= Dmps.SwitcherInputs.Count) + { + //Shift video inputs by 5 for weird DMPS3-4K indexing + output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number + 5); + } + else + { + //Shift analog inputs back to inputs 1-5 + output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number - Dmps.SwitcherInputs.Count); + } } } @@ -1122,10 +1241,91 @@ namespace PepperDash.Essentials.DM public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType) { - var input = inputSelector == 0 ? null : Dmps.SwitcherInputs[inputSelector]; - var output = Dmps.SwitcherOutputs[outputSelector]; + if (EnableRouting == false) + { + return; + } - ExecuteSwitch(input, output, sigType); + Debug.Console(1, this, "Attempting a numeric switch from input {0} to output {1} {2}", inputSelector, outputSelector, sigType); + + if((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) + { + if (inputSelector <= Dmps.SwitcherInputs.Count && outputSelector <= Dmps.SwitcherOutputs.Count) + { + var input = inputSelector == 0 ? null : Dmps.SwitcherInputs[inputSelector]; + var output = Dmps.SwitcherOutputs[outputSelector]; + + ExecuteSwitch(input, output, sigType); + } + } + else if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) + { + //Special case for DMPS-4K digital audio output + if (Global.ControlSystemIsDmps4kType) + { + if (DigitalAudioOutputs.ContainsKey(outputSelector)) + { + if (inputSelector == 0) //Clear action + { + DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(0, 0, eRoutingSignalType.Audio); + } + else if (inputSelector <= Dmps.SwitcherInputs.Count) //DMPS-4K video inputs, set to audio follows video + { + DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(3, 0, eRoutingSignalType.Audio); + //Force video route since it is now set so audio follows video + ExecuteNumericSwitch(inputSelector, outputSelector, eRoutingSignalType.Video); + } + else if (inputSelector == Dmps.SwitcherInputs.Count + 6) + { + //Set to mix 1 + DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(1, 0, eRoutingSignalType.Audio); + } + else if (inputSelector == Dmps.SwitcherInputs.Count + 7) + { + //Set to mix 2 + DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(2, 0, eRoutingSignalType.Audio); + } + } + else if (inputSelector <= (Dmps.SwitcherInputs.Count + 5) && outputSelector <= Dmps.SwitcherOutputs.Count) + { + var output = Dmps.SwitcherOutputs[outputSelector] as DMOutput; + if (inputSelector == 0) + { + output.AudioOutSource = eDmps34KAudioOutSource.NoRoute; + } + else if(inputSelector > Dmps.SwitcherInputs.Count) + { + //Shift analog inputs back to inputs 1-5 + Debug.Console(1, this, "Attempting analog route input {0} to output {1}", inputSelector - Dmps.SwitcherInputs.Count, outputSelector); + output.AudioOutSource = (eDmps34KAudioOutSource)(inputSelector - Dmps.SwitcherInputs.Count); + } + else if (inputSelector <= Dmps.SwitcherInputs.Count) + { + var input = Dmps.SwitcherInputs[inputSelector] as DMInput; + if (input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaInput || input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaNoStreamingInput) + { + //Special case for weird AirMedia indexing + if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl) + output.AudioOutSource = eDmps34KAudioOutSource.AirMedia8; + else if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) + output.AudioOutSource = eDmps34KAudioOutSource.AirMedia9; + } + else + { + //Shift video inputs by 5 for weird DMPS3-4K indexing + output.AudioOutSource = (eDmps34KAudioOutSource)(inputSelector + 5); + } + } + } + } + + else if (inputSelector <= Dmps.SwitcherInputs.Count && outputSelector <= Dmps.SwitcherOutputs.Count) + { + var output = Dmps.SwitcherOutputs[outputSelector] as DMOutput; + var input = Dmps.SwitcherInputs[inputSelector] as DMInput; + output.AudioOut = input; + } + } } #endregion 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 ea3dbd5d..41b07237 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -93,6 +93,7 @@ + From 5b94d89bc36df25563599615a6b6b3e5bd0ff53c Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 15 Jun 2022 20:26:32 -0400 Subject: [PATCH 09/30] Improvements for DMPS3-4K-150 types --- .../PepperDashEssentialsBase/Global/Global.cs | 44 ++- .../Chassis/DmpsAudioOutputController.cs | 333 +++++++++++++----- .../Chassis/DmpsDigitalOutputController.cs | 8 +- .../Chassis/DmpsRoutingController.cs | 105 ++++-- 4 files changed, 356 insertions(+), 134 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs index 9d792437..2bafc2ae 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronDataStore; using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DM; using PepperDash.Core; using PepperDash.Essentials.License; @@ -39,7 +40,14 @@ namespace PepperDash.Essentials.Core { get { - return ControlSystem.ControllerPrompt.ToLower().IndexOf("dmps") > -1; + if(ControlSystem.SystemControl != null) + { + if(ControlSystem.SystemControl.SystemControlType > 0) + { + return true; + } + } + return false; } } @@ -50,7 +58,39 @@ namespace PepperDash.Essentials.Core { get { - return ControlSystemIsDmpsType && ControlSystem.ControllerPrompt.ToLower().IndexOf("4k") > -1; + if(ControlSystem.SystemControl != null) + { + if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K150CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) + { + return true; + } + } + return false; + } + } + + /// + /// True when the processor type is a DMPS 4K 200/300/250/350 variant + /// + public static bool ControlSystemIsDmps4k3xxType + { + get + { + if(ControlSystem.SystemControl != null) + { + if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) + { + return true; + } + } + return false; } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs index 60943270..c3ed2354 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs @@ -17,60 +17,89 @@ using PepperDash.Essentials.DM.Config; namespace PepperDash.Essentials.DM { /// - /// Exposes the volume levels for Program, Aux1 or Aux2 outputs on a DMPS3 chassis + /// Exposes the volume levels for Program, Aux1, Aux2, Codec1, Codec2, and Digital outputs on a DMPS3 chassis /// public class DmpsAudioOutputController : EssentialsBridgeableDevice { - Card.Dmps3OutputBase OutputCard; - public DmpsAudioOutput MasterVolumeLevel { get; private set; } public DmpsAudioOutput SourceVolumeLevel { get; private set; } public DmpsAudioOutput MicsMasterVolumeLevel { get; private set; } public DmpsAudioOutput Codec1VolumeLevel { get; private set; } public DmpsAudioOutput Codec2VolumeLevel { get; private set; } + public DmpsAudioOutputController(string key, string name, DMOutput card, Card.Dmps3DmHdmiAudioOutput.Dmps3AudioOutputStream stream) + : base(key, name) + { + card.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); + var output = new Dmps3AudioOutputWithMixerBase(stream); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + } + public DmpsAudioOutputController(string key, string name, DMOutput card, Card.Dmps3DmHdmiAudioOutput.Dmps3DmHdmiOutputStream stream) + : base(key, name) + { + card.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); + var output = new Dmps3AudioOutputWithMixerBase(stream); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + } + public DmpsAudioOutputController(string key, string name, Card.Dmps3OutputBase card) : base(key, name) { - OutputCard = card; - OutputCard.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); - - SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source); - MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster); + card.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); if (card is Card.Dmps3ProgramOutput) { - var output = card as Card.Dmps3ProgramOutput; - MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); - Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); - Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); + var programOutput = card as Card.Dmps3ProgramOutput; + var output = new Dmps3AudioOutputWithMixerBase(card, programOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(output, eDmpsLevelType.Master, programOutput.OutputEqualizer); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); + Codec1VolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Codec1); + Codec2VolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Codec2); } else if (card is Card.Dmps3Aux1Output) { - var output = card as Card.Dmps3Aux1Output; - MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); - Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); + var auxOutput = card as Card.Dmps3Aux1Output; + var output = new Dmps3AudioOutputWithMixerBase(card, auxOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(output, eDmpsLevelType.Master, auxOutput.OutputEqualizer); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); + Codec2VolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Codec2); } else if (card is Card.Dmps3Aux2Output) { - var output = card as Card.Dmps3Aux2Output; - MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(card, eDmpsLevelType.Master, output.OutputMixer, output.OutputEqualizer); - Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); + var auxOutput = card as Card.Dmps3Aux2Output; + var output = new Dmps3AudioOutputWithMixerBase(card, auxOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixerAndEq(output, eDmpsLevelType.Master, auxOutput.OutputEqualizer); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); + Codec1VolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Codec1); } else if (card is Card.Dmps3DigitalMixOutput) { - var output = card as Card.Dmps3DigitalMixOutput; - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + var mixOutput = card as Card.Dmps3DigitalMixOutput; + var output = new Dmps3AudioOutputWithMixerBase(card, mixOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); } else if (card is Card.Dmps3HdmiOutput) { - var output = card as Card.Dmps3HdmiOutput; - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + var hdmiOutput = card as Card.Dmps3HdmiOutput; + var output = new Dmps3AudioOutputWithMixerBase(card, hdmiOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); } else if (card is Card.Dmps3DmOutput) { - var output = card as Card.Dmps3DmOutput; - MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, output.OutputMixer); + var dmOutput = card as Card.Dmps3DmOutput; + var output = new Dmps3AudioOutputWithMixerBase(card, dmOutput.OutputMixer); + MasterVolumeLevel = new DmpsAudioOutputWithMixer(output, eDmpsLevelType.Master); + SourceVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.Source); + MicsMasterVolumeLevel = new DmpsAudioOutput(output, eDmpsLevelType.MicsMaster); } } @@ -250,8 +279,8 @@ namespace PepperDash.Essentials.DM public class DmpsAudioOutputWithMixerAndEq : DmpsAudioOutputWithMixer { private CrestronControlSystem.Dmps3OutputEqualizer Eq; - public DmpsAudioOutputWithMixerAndEq(Card.Dmps3OutputBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputMixer mixer, CrestronControlSystem.Dmps3OutputEqualizer eq) - : base(output, type, mixer) + public DmpsAudioOutputWithMixerAndEq(Dmps3AudioOutputWithMixerBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputEqualizer eq) + : base(output, type) { Eq = eq; } @@ -265,19 +294,19 @@ namespace PepperDash.Essentials.DM public class DmpsAudioOutputWithMixer : DmpsAudioOutput { - IDmps3OutputMixer Mixer; + Dmps3AudioOutputWithMixerBase Output; - public DmpsAudioOutputWithMixer(Card.Dmps3OutputBase output, eDmpsLevelType type, IDmps3OutputMixer mixer) + public DmpsAudioOutputWithMixer(Dmps3AudioOutputWithMixerBase output, eDmpsLevelType type) : base(output, type) { - Mixer = mixer; + Output = output; GetVolumeMax(); GetVolumeMin(); } public void GetVolumeMin() { - MinLevel = (short)Mixer.MinVolumeFeedback.UShortValue; + MinLevel = (short)Output.MinVolumeFeedback.UShortValue; if (VolumeLevelScaledFeedback != null) { VolumeLevelScaledFeedback.FireUpdate(); @@ -286,7 +315,7 @@ namespace PepperDash.Essentials.DM public void GetVolumeMax() { - MaxLevel = (short)Mixer.MaxVolumeFeedback.UShortValue; + MaxLevel = (short)Output.MaxVolumeFeedback.UShortValue; if (VolumeLevelScaledFeedback != null) { VolumeLevelScaledFeedback.FireUpdate(); @@ -295,32 +324,22 @@ namespace PepperDash.Essentials.DM public void RecallPreset(ushort preset) { - if (Mixer is CrestronControlSystem.Dmps3OutputMixer) - { - var presetMixer = Mixer as CrestronControlSystem.Dmps3OutputMixer; - Debug.Console(1, "DMPS Recalling Preset {0}", preset); - presetMixer.PresetNumber.UShortValue = preset; - presetMixer.RecallPreset(); + Output.PresetNumber.UShortValue = preset; + Output.RecallPreset(); + if (!Global.ControlSystemIsDmps4kType) + { //Recall startup volume for main volume level as DMPS3(non-4K) presets don't affect the main volume RecallStartupVolume(); } - else if (Mixer is CrestronControlSystem.Dmps3AttachableOutputMixer) - { - var presetMixer = Mixer as CrestronControlSystem.Dmps3AttachableOutputMixer; - Debug.Console(1, "DMPS Recalling Preset {0}", preset); - presetMixer.PresetNumber.UShortValue = preset; - presetMixer.RecallPreset(); - } - } public void RecallStartupVolume() { - ushort startupVol = Mixer.StartupVolumeFeedback.UShortValue; + ushort startupVol = Output.StartupVolumeFeedback.UShortValue; //Reset startup vol due to bug on DMPS3 where getting the value from above method clears the startup volume - Mixer.StartupVolume.UShortValue = startupVol; - Debug.Console(1, "DMPS Recalling {0} Startup Volume {1}", Output.Name, startupVol); + Output.StartupVolume.UShortValue = startupVol; + Debug.Console(1, "DMPS Recalling Startup Volume {0}", startupVol); SetVolume(startupVol); MuteOff(); } @@ -329,7 +348,6 @@ namespace PepperDash.Essentials.DM public class DmpsAudioOutput : IBasicVolumeWithFeedback { private UShortInputSig Level; - protected Card.Dmps3OutputBase Output; private bool EnableVolumeSend; private ushort VolumeLevelInput; protected short MinLevel { get; set; } @@ -345,9 +363,8 @@ namespace PepperDash.Essentials.DM Action VolumeUpAction; Action VolumeDownAction; - public DmpsAudioOutput(Card.Dmps3OutputBase output, eDmpsLevelType type) + public DmpsAudioOutput(Dmps3AudioOutputBase output, eDmpsLevelType type) { - Output = output; VolumeLevelInput = 0; EnableVolumeSend = false; Type = type; @@ -359,47 +376,46 @@ namespace PepperDash.Essentials.DM case eDmpsLevelType.Master: { Level = output.MasterVolume; - - MuteFeedback = new BoolFeedback(new Func(() => Output.MasterMuteOnFeedBack.BoolValue)); - VolumeLevelFeedback = new IntFeedback(new Func(() => Output.MasterVolumeFeedBack.UShortValue)); - MuteOnAction = new Action(Output.MasterMuteOn); - MuteOffAction = new Action(Output.MasterMuteOff); - VolumeUpAction = new Action((b) => Output.MasterVolumeUp.BoolValue = b); - VolumeDownAction = new Action((b) => Output.MasterVolumeDown.BoolValue = b); + MuteFeedback = new BoolFeedback(new Func(() => output.MasterMuteOnFeedBack.BoolValue)); + VolumeLevelFeedback = new IntFeedback(new Func(() => output.MasterVolumeFeedBack.UShortValue)); + MuteOnAction = new Action(output.MasterMuteOn); + MuteOffAction = new Action(output.MasterMuteOff); + VolumeUpAction = new Action((b) => output.MasterVolumeUp.BoolValue = b); + VolumeDownAction = new Action((b) => output.MasterVolumeDown.BoolValue = b); break; } case eDmpsLevelType.MicsMaster: { - Level = output.MicMasterLevel; - - MuteFeedback = new BoolFeedback(new Func(() => Output.MicMasterMuteOnFeedBack.BoolValue)); - VolumeLevelFeedback = new IntFeedback(new Func(() => Output.MicMasterLevelFeedBack.UShortValue)); - MuteOnAction = new Action(Output.MicMasterMuteOn); - MuteOffAction = new Action(Output.MicMasterMuteOff); - VolumeUpAction = new Action((b) => Output.MicMasterLevelUp.BoolValue = b); - VolumeDownAction = new Action((b) => Output.MicMasterLevelDown.BoolValue = b); + if (output.Card is Card.Dmps3OutputBase) + { + var micOutput = output.Card as Card.Dmps3OutputBase; + Level = micOutput.MicMasterLevel; + MuteFeedback = new BoolFeedback(new Func(() => micOutput.MicMasterMuteOnFeedBack.BoolValue)); + VolumeLevelFeedback = new IntFeedback(new Func(() => micOutput.MicMasterLevelFeedBack.UShortValue)); + MuteOnAction = new Action(micOutput.MicMasterMuteOn); + MuteOffAction = new Action(micOutput.MicMasterMuteOff); + VolumeUpAction = new Action((b) => micOutput.MicMasterLevelUp.BoolValue = b); + VolumeDownAction = new Action((b) => micOutput.MicMasterLevelDown.BoolValue = b); + } break; } case eDmpsLevelType.Source: { Level = output.SourceLevel; - - MuteFeedback = new BoolFeedback(new Func(() => Output.SourceMuteOnFeedBack.BoolValue)); - VolumeLevelFeedback = new IntFeedback(new Func(() => Output.SourceLevelFeedBack.UShortValue)); - MuteOnAction = new Action(Output.SourceMuteOn); - MuteOffAction = new Action(Output.SourceMuteOff); - VolumeUpAction = new Action((b) => Output.SourceLevelUp.BoolValue = b); - VolumeDownAction = new Action((b) => Output.SourceLevelDown.BoolValue = b); + MuteFeedback = new BoolFeedback(new Func(() => output.SourceMuteOnFeedBack.BoolValue)); + VolumeLevelFeedback = new IntFeedback(new Func(() => output.SourceLevelFeedBack.UShortValue)); + MuteOnAction = new Action(output.SourceMuteOn); + MuteOffAction = new Action(output.SourceMuteOff); + VolumeUpAction = new Action((b) => output.SourceLevelUp.BoolValue = b); + VolumeDownAction = new Action((b) => output.SourceLevelDown.BoolValue = b); break; } case eDmpsLevelType.Codec1: { - var programOutput = output as Card.Dmps3ProgramOutput; - - if (programOutput != null) + if (output.Card is Card.Dmps3ProgramOutput) { + var programOutput = output.Card as Card.Dmps3ProgramOutput; Level = programOutput.Codec1Level; - MuteFeedback = new BoolFeedback(new Func(() => programOutput.CodecMute1OnFeedback.BoolValue)); VolumeLevelFeedback = new IntFeedback(new Func(() => programOutput.Codec1LevelFeedback.UShortValue)); MuteOnAction = new Action(programOutput.Codec1MuteOn); @@ -407,12 +423,10 @@ namespace PepperDash.Essentials.DM VolumeUpAction = new Action((b) => programOutput.Codec1LevelUp.BoolValue = b); VolumeDownAction = new Action((b) => programOutput.Codec1LevelDown.BoolValue = b); } - else + else if (output.Card is Card.Dmps3Aux2Output) { - var auxOutput = output as Card.Dmps3Aux2Output; - + var auxOutput = output.Card as Card.Dmps3Aux2Output; Level = auxOutput.Codec1Level; - MuteFeedback = new BoolFeedback(new Func(() => auxOutput.CodecMute1OnFeedback.BoolValue)); VolumeLevelFeedback = new IntFeedback(new Func(() => auxOutput.Codec1LevelFeedback.UShortValue)); MuteOnAction = new Action(auxOutput.Codec1MuteOn); @@ -424,12 +438,10 @@ namespace PepperDash.Essentials.DM } case eDmpsLevelType.Codec2: { - var programOutput = output as Card.Dmps3ProgramOutput; - - if (programOutput != null) + if (output.Card is Card.Dmps3ProgramOutput) { + var programOutput = output.Card as Card.Dmps3ProgramOutput; Level = programOutput.Codec2Level; - MuteFeedback = new BoolFeedback(new Func(() => programOutput.CodecMute1OnFeedback.BoolValue)); VolumeLevelFeedback = new IntFeedback(new Func(() => programOutput.Codec2LevelFeedback.UShortValue)); MuteOnAction = new Action(programOutput.Codec2MuteOn); @@ -437,12 +449,11 @@ namespace PepperDash.Essentials.DM VolumeUpAction = new Action((b) => programOutput.Codec2LevelUp.BoolValue = b); VolumeDownAction = new Action((b) => programOutput.Codec2LevelDown.BoolValue = b); } - else + else if (output.Card is Card.Dmps3Aux1Output) { - var auxOutput = output as Card.Dmps3Aux1Output; + var auxOutput = output.Card as Card.Dmps3Aux1Output; Level = auxOutput.Codec2Level; - MuteFeedback = new BoolFeedback(new Func(() => auxOutput.CodecMute2OnFeedback.BoolValue)); VolumeLevelFeedback = new IntFeedback(new Func(() => auxOutput.Codec2LevelFeedback.UShortValue)); MuteOnAction = new Action(auxOutput.Codec2MuteOn); @@ -463,7 +474,6 @@ namespace PepperDash.Essentials.DM public void SetVolumeScaled(ushort level) { - Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} level:{1} min:{2} max:{3}", Output.Name, level.ToString(), MinLevel.ToString(), MaxLevel.ToString()); if (ushort.MaxValue + MinLevel != 0) { VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel); @@ -477,7 +487,6 @@ namespace PepperDash.Essentials.DM public ushort ScaleVolumeFeedback(ushort level) { short signedLevel = (short)level; - Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} feedback:{1} min:{2} max:{3}", Output.Name, signedLevel.ToString(), MinLevel.ToString(), MaxLevel.ToString()); if (MaxLevel - MinLevel != 0) { @@ -538,6 +547,150 @@ namespace PepperDash.Essentials.DM #endregion } + public class Dmps3AudioOutputWithMixerBase : Dmps3AudioOutputBase + { + public UShortOutputSig MinVolumeFeedback { get; private set; } + public UShortOutputSig MaxVolumeFeedback { get; private set; } + public UShortInputSig StartupVolume { get; private set; } + public UShortOutputSig StartupVolumeFeedback { get; private set; } + public UShortInputSig PresetNumber { get; private set; } + + public Action RecallPreset { get; private set; } + + public Dmps3AudioOutputWithMixerBase(Card.Dmps3OutputBase card, CrestronControlSystem.Dmps3OutputMixer mixer) + : base(card) + { + MinVolumeFeedback = mixer.MinVolumeFeedback; + MaxVolumeFeedback = mixer.MaxVolumeFeedback; + StartupVolume = mixer.StartupVolume; + StartupVolumeFeedback = mixer.StartupVolumeFeedback; + PresetNumber = mixer.PresetNumber; + + RecallPreset = new Action(mixer.RecallPreset); + } + + public Dmps3AudioOutputWithMixerBase(Card.Dmps3OutputBase card, CrestronControlSystem.Dmps3AttachableOutputMixer mixer) + : base(card) + { + MinVolumeFeedback = mixer.MinVolumeFeedback; + MaxVolumeFeedback = mixer.MaxVolumeFeedback; + StartupVolume = mixer.StartupVolume; + StartupVolumeFeedback = mixer.StartupVolumeFeedback; + PresetNumber = mixer.PresetNumber; + + RecallPreset = new Action(mixer.RecallPreset); + } + + public Dmps3AudioOutputWithMixerBase(Card.Dmps3DmHdmiAudioOutput.Dmps3AudioOutputStream stream) + : base(stream) + { + var mixer = stream.OutputMixer; + MinVolumeFeedback = mixer.MinVolumeFeedback; + MaxVolumeFeedback = mixer.MaxVolumeFeedback; + StartupVolume = mixer.StartupVolume; + StartupVolumeFeedback = mixer.StartupVolumeFeedback; + PresetNumber = stream.PresetNumber; + RecallPreset = new Action(stream.RecallPreset); + } + + public Dmps3AudioOutputWithMixerBase(Card.Dmps3DmHdmiAudioOutput.Dmps3DmHdmiOutputStream stream) + : base(stream) + { + var mixer = stream.OutputMixer; + MinVolumeFeedback = mixer.MinVolumeFeedback; + MaxVolumeFeedback = mixer.MaxVolumeFeedback; + StartupVolume = mixer.StartupVolume; + StartupVolumeFeedback = mixer.StartupVolumeFeedback; + PresetNumber = stream.PresetNumber; + RecallPreset = new Action(stream.RecallPreset); + } + } + public class Dmps3AudioOutputBase + { + public DMOutput Card { get; private set; } + public BoolOutputSig MasterMuteOffFeedBack { get; private set; } + public BoolOutputSig MasterMuteOnFeedBack { get; private set; } + public UShortInputSig MasterVolume { get; private set; } + public UShortOutputSig MasterVolumeFeedBack { get; private set; } + public BoolInputSig MasterVolumeUp { get; private set; } + public BoolInputSig MasterVolumeDown { get; private set; } + public BoolOutputSig SourceMuteOffFeedBack { get; private set; } + public BoolOutputSig SourceMuteOnFeedBack { get; private set; } + public UShortInputSig SourceLevel { get; private set; } + public UShortOutputSig SourceLevelFeedBack { get; private set; } + public BoolInputSig SourceLevelUp { get; private set; } + public BoolInputSig SourceLevelDown { get; private set; } + + public Action MasterMuteOff { get; private set; } + public Action MasterMuteOn { get; private set; } + public Action SourceMuteOff { get; private set; } + public Action SourceMuteOn { get; private set; } + + public Dmps3AudioOutputBase(Card.Dmps3OutputBase card) + { + Card = card; + MasterMuteOffFeedBack = card.MasterMuteOffFeedBack; + MasterMuteOnFeedBack = card.MasterMuteOnFeedBack; + MasterVolume = card.MasterVolume; + MasterVolumeFeedBack = card.MasterVolumeFeedBack; + MasterVolumeUp = card.MasterVolumeUp; + MasterVolumeDown = card.MasterVolumeDown; + SourceMuteOffFeedBack = card.SourceMuteOffFeedBack; + SourceMuteOnFeedBack = card.SourceMuteOnFeedBack; + SourceLevel = card.SourceLevel; + SourceLevelFeedBack = card.SourceLevelFeedBack; + SourceLevelUp = card.SourceLevelUp; + SourceLevelDown = card.SourceLevelDown; + + MasterMuteOff = new Action(card.MasterMuteOff); + MasterMuteOn = new Action(card.MasterMuteOn); + SourceMuteOff = new Action(card.SourceMuteOff); + SourceMuteOn = new Action(card.SourceMuteOn); + } + + public Dmps3AudioOutputBase(Card.Dmps3DmHdmiAudioOutput.Dmps3AudioOutputStream stream) + { + MasterMuteOffFeedBack = stream.MasterMuteOffFeedBack; + MasterMuteOnFeedBack = stream.MasterMuteOnFeedBack; + MasterVolume = stream.MasterVolume; + MasterVolumeFeedBack = stream.MasterVolumeFeedBack; + MasterVolumeUp = stream.MasterVolumeUp; + MasterVolumeDown = stream.MasterVolumeDown; + SourceMuteOffFeedBack = stream.SourceMuteOffFeedBack; + SourceMuteOnFeedBack = stream.SourceMuteOnFeedBack; + SourceLevel = stream.SourceLevel; + SourceLevelFeedBack = stream.SourceLevelFeedBack; + SourceLevelUp = stream.SourceLevelUp; + SourceLevelDown = stream.SourceLevelDown; + + MasterMuteOff = new Action(stream.MasterMuteOff); + MasterMuteOn = new Action(stream.MasterMuteOn); + SourceMuteOff = new Action(stream.SourceMuteOff); + SourceMuteOn = new Action(stream.SourceMuteOn); + } + + public Dmps3AudioOutputBase(Card.Dmps3DmHdmiAudioOutput.Dmps3DmHdmiOutputStream stream) + { + MasterMuteOffFeedBack = stream.MasterMuteOffFeedBack; + MasterMuteOnFeedBack = stream.MasterMuteOnFeedBack; + MasterVolume = stream.MasterVolume; + MasterVolumeFeedBack = stream.MasterVolumeFeedBack; + MasterVolumeUp = stream.MasterVolumeUp; + MasterVolumeDown = stream.MasterVolumeDown; + SourceMuteOffFeedBack = stream.SourceMuteOffFeedBack; + SourceMuteOnFeedBack = stream.SourceMuteOnFeedBack; + SourceLevel = stream.SourceLevel; + SourceLevelFeedBack = stream.SourceLevelFeedBack; + SourceLevelUp = stream.SourceLevelUp; + SourceLevelDown = stream.SourceLevelDown; + + MasterMuteOff = new Action(stream.MasterMuteOff); + MasterMuteOn = new Action(stream.MasterMuteOn); + SourceMuteOff = new Action(stream.SourceMuteOff); + SourceMuteOn = new Action(stream.SourceMuteOn); + } + } + public enum eDmpsLevelType { Master, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs index 49b5c1c5..70465783 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsDigitalOutputController.cs @@ -15,7 +15,7 @@ namespace PepperDash.Essentials.DM /// /// /// - public class DmpsDigitalOutputController : Device, IRoutingNumericWithFeedback, IHasFeedback + public class DmpsDigitalOutputController : Device, IRoutingNumeric, IHasFeedback { public Card.Dmps3OutputBase OutputCard { get; protected set; } @@ -161,11 +161,5 @@ namespace PepperDash.Essentials.DM } #endregion - - #region IRoutingFeedback Members - - public event EventHandler NumericSwitchChange; - - #endregion } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 55c49a96..074880e6 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -418,17 +418,11 @@ namespace PepperDash.Essentials.DM private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) { - if (Global.ControlSystemIsDmps4kType) + if (Global.ControlSystemIsDmps4k3xxType) { - //DMPS-4K audio inputs 1-5 are aux inputs, add them after regular dm cards - for (ushort i = 1; i <= 5; i++) - { - trilist.StringInput[joinMap.InputAudioNames.JoinNumber + i - 1 + (ushort)Dmps.SwitcherInputs.Count].StringValue = String.Format("Aux Input {0}", i); - } - //Add DMPS-4K mixer input names to end of inputs - trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 5].StringValue = "Digital Mixer 1"; - trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 6].StringValue = "Digital Mixer 2"; + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 4].StringValue = "Digital Mixer 1"; + trilist.StringInput[joinMap.InputAudioNames.JoinNumber + (uint)Dmps.SwitcherInputs.Count + 5].StringValue = "Digital Mixer 2"; } for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++) { @@ -445,9 +439,19 @@ namespace PepperDash.Essentials.DM if (InputNameFeedbacks.ContainsKey(ioSlot) && InputNameFeedbacks[ioSlot] != null) { - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]); - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]); + if (Dmps.SwitcherInputs[ioSlot] is Card.Dmps3AnalogAudioInput) + { + for (uint j = ioSlot; j < ioSlot + 5; j++) + { + InputNameFeedbacks[j].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + j - 1]); + } + } + else + { + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]); + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]); + } } trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s => @@ -509,7 +513,7 @@ namespace PepperDash.Essentials.DM }); AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() => { - if (!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { if (outputCard.AudioOutFeedback != null) { @@ -526,9 +530,9 @@ namespace PepperDash.Essentials.DM if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 0) return 0; else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 1) - return (ushort)Dmps.SwitcherInputs.Count + 6; + return (ushort)Dmps.SwitcherInputs.Count + 5; else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 2) - return (ushort)Dmps.SwitcherInputs.Count + 7; + return (ushort)Dmps.SwitcherInputs.Count + 6; else if (DigitalAudioOutputs[outputCard.Number].AudioSourceNumericFeedback.UShortValue == 3) return (ushort)outputCard.VideoOutFeedback.Number; else @@ -552,7 +556,7 @@ namespace PepperDash.Essentials.DM else if ((ushort)outputCard.AudioOutSourceFeedback <= 5) { //Move analog inputs to after regular dm cards - return (ushort)outputCard.AudioOutSourceFeedback + (ushort)Dmps.SwitcherInputs.Count; + return (ushort)outputCard.AudioOutSourceFeedback + (ushort)Dmps.SwitcherInputs.Count - 1; } else { @@ -586,7 +590,7 @@ namespace PepperDash.Essentials.DM }); OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() => { - if (!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null) { @@ -692,7 +696,6 @@ namespace PepperDash.Essentials.DM else if (inputCard is Card.Dmps3HdmiInput) { var hdmiInputCard = inputCard as Card.Dmps3HdmiInput; - var cecPort = hdmiInputCard.HdmiInputPort; AddInputPortWithDebug(number, string.Format("HdmiIn{0}", number), eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort); @@ -724,17 +727,37 @@ namespace PepperDash.Essentials.DM else if (inputCard is Card.Dmps3DmInput) { var hdmiInputCard = inputCard as Card.Dmps3DmInput; - var cecPort = hdmiInputCard.DmInputPort; AddInputPortWithDebug(number, string.Format("DmIn{0}", number), eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort); } + else if (inputCard is Card.Dmps3VgaInput) + { + AddInputPortWithDebug(number, string.Format("VgaIn{0}", number), eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Vga); + } else if (inputCard is Card.Dmps3AirMediaInput) { - var airMediaInputCard = inputCard as Card.Dmps3AirMediaInput; - AddInputPortWithDebug(number, string.Format("AirMediaIn{0}", number), eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming); } + else if (inputCard is Card.Dmps3AnalogAudioInput) + { + for (uint i = 0; i <= 4; i++) + { + uint j = i + 1; + uint input = i + number; + InputNameFeedbacks[input] = new StringFeedback(() => + { + if (InputNames.ContainsKey(input)) + { + return InputNames[input]; + } + else + { + return String.Format("Aux Input {0}", j); + } + }); + } + } } @@ -796,7 +819,6 @@ namespace PepperDash.Essentials.DM else if (outputCard is Card.Dmps3DmOutput) { AddDmOutputPort(number); - var audioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number), string.Format("Dm Audio Output {0}", number), outputCard as Card.Dmps3DmOutput); DeviceManager.AddDevice(audioOutput); } @@ -807,6 +829,19 @@ namespace PepperDash.Essentials.DM DigitalAudioOutputs.Add(number, audioOutput); DeviceManager.AddDevice(audioOutput); } + else if (outputCard is Card.Dmps3DmHdmiAudioOutput) + { + var hdmiOutputCard = outputCard as Card.Dmps3DmHdmiAudioOutput; + var cecPort = hdmiOutputCard.HdmiOutputPort; + AddHdmiOutputPort(number, cecPort); + AddDmOutputPort(number); + AddAudioOnlyOutputPort(number, "Program"); + + var audioOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput", number), string.Format("Program Audio Output {0}", number), hdmiOutputCard, hdmiOutputCard.AudioOutputStream); + DeviceManager.AddDevice(audioOutput); + var digitalAudioOutput = new DmpsAudioOutputController(string.Format("processor-digitalAudioOutput{0}", number), string.Format("Hdmi Audio Output {0}", number), hdmiOutputCard, hdmiOutputCard.DmHdmiOutputStream); + DeviceManager.AddDevice(digitalAudioOutput); + } else if (outputCard is Card.Dmps3ProgramOutput) { AddAudioOnlyOutputPort(number, "Program"); @@ -1041,7 +1076,7 @@ namespace PepperDash.Essentials.DM } else if (args.EventId == DMOutputEventIds.AudioOutEventId) { - if (!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { if (outputCard != null && outputCard.AudioOutFeedback != null) { @@ -1180,7 +1215,7 @@ namespace PepperDash.Essentials.DM if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) { - if(!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { output.AudioOut = input; } @@ -1198,7 +1233,7 @@ namespace PepperDash.Essentials.DM else if (Dmps.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) output.AudioOutSource = eDmps34KAudioOutSource.AirMedia9; } - else if (input.Number <= Dmps.SwitcherInputs.Count) + else if (input.Number < Dmps.SwitcherInputs.Count) { //Shift video inputs by 5 for weird DMPS3-4K indexing output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number + 5); @@ -1206,7 +1241,7 @@ namespace PepperDash.Essentials.DM else { //Shift analog inputs back to inputs 1-5 - output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number - Dmps.SwitcherInputs.Count); + output.AudioOutSource = (eDmps34KAudioOutSource)(input.Number - Dmps.SwitcherInputs.Count + 1); } } } @@ -1261,7 +1296,7 @@ namespace PepperDash.Essentials.DM else if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) { //Special case for DMPS-4K digital audio output - if (Global.ControlSystemIsDmps4kType) + if (Global.ControlSystemIsDmps4k3xxType) { if (DigitalAudioOutputs.ContainsKey(outputSelector)) { @@ -1269,37 +1304,37 @@ namespace PepperDash.Essentials.DM { DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(0, 0, eRoutingSignalType.Audio); } - else if (inputSelector <= Dmps.SwitcherInputs.Count) //DMPS-4K video inputs, set to audio follows video + else if (inputSelector < Dmps.SwitcherInputs.Count) //DMPS-4K video inputs, set to audio follows video { DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(3, 0, eRoutingSignalType.Audio); //Force video route since it is now set so audio follows video ExecuteNumericSwitch(inputSelector, outputSelector, eRoutingSignalType.Video); } - else if (inputSelector == Dmps.SwitcherInputs.Count + 6) + else if (inputSelector == Dmps.SwitcherInputs.Count + 5) { //Set to mix 1 DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(1, 0, eRoutingSignalType.Audio); } - else if (inputSelector == Dmps.SwitcherInputs.Count + 7) + else if (inputSelector == Dmps.SwitcherInputs.Count + 6) { //Set to mix 2 DigitalAudioOutputs[outputSelector].ExecuteNumericSwitch(2, 0, eRoutingSignalType.Audio); } } - else if (inputSelector <= (Dmps.SwitcherInputs.Count + 5) && outputSelector <= Dmps.SwitcherOutputs.Count) + else if (inputSelector <= (Dmps.SwitcherInputs.Count + 4) && outputSelector <= Dmps.SwitcherOutputs.Count) { var output = Dmps.SwitcherOutputs[outputSelector] as DMOutput; if (inputSelector == 0) { output.AudioOutSource = eDmps34KAudioOutSource.NoRoute; } - else if(inputSelector > Dmps.SwitcherInputs.Count) + else if(inputSelector >= (Dmps.SwitcherInputs.Count)) { //Shift analog inputs back to inputs 1-5 - Debug.Console(1, this, "Attempting analog route input {0} to output {1}", inputSelector - Dmps.SwitcherInputs.Count, outputSelector); - output.AudioOutSource = (eDmps34KAudioOutSource)(inputSelector - Dmps.SwitcherInputs.Count); + Debug.Console(1, this, "Attempting analog route input {0} to output {1}", inputSelector - Dmps.SwitcherInputs.Count + 1, outputSelector); + output.AudioOutSource = (eDmps34KAudioOutSource)(inputSelector - Dmps.SwitcherInputs.Count + 1); } - else if (inputSelector <= Dmps.SwitcherInputs.Count) + else if (inputSelector < Dmps.SwitcherInputs.Count) { var input = Dmps.SwitcherInputs[inputSelector] as DMInput; if (input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaInput || input.CardInputOutputType == eCardInputOutputType.Dmps3AirMediaNoStreamingInput) From 53c9f9e6640bc5143f4cd0f9c8922cc7b1d29439 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Fri, 17 Jun 2022 14:42:51 -0400 Subject: [PATCH 10/30] Fixes issue where sometimes clear route doesn't work on DMPS3 --- .../Essentials_DM/Chassis/DmpsRoutingController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 074880e6..17aa1b1d 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -1357,7 +1357,7 @@ namespace PepperDash.Essentials.DM else if (inputSelector <= Dmps.SwitcherInputs.Count && outputSelector <= Dmps.SwitcherOutputs.Count) { var output = Dmps.SwitcherOutputs[outputSelector] as DMOutput; - var input = Dmps.SwitcherInputs[inputSelector] as DMInput; + var input = inputSelector == 0 ? null : Dmps.SwitcherInputs[inputSelector] as DMInput; output.AudioOut = input; } } From d849e4185cbac3685c82a3f40926e64173411d22 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Mon, 27 Jun 2022 09:35:38 -0400 Subject: [PATCH 11/30] Fixes clear audio route on DMPS3-4K-150. Fixes output names on join map for DMPS3-4K-150 --- .../Essentials_DM/Chassis/DmpsAudioOutputController.cs | 2 +- .../Essentials_DM/Chassis/DmpsRoutingController.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs index c3ed2354..c0f0ca65 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsAudioOutputController.cs @@ -327,7 +327,7 @@ namespace PepperDash.Essentials.DM Output.PresetNumber.UShortValue = preset; Output.RecallPreset(); - if (!Global.ControlSystemIsDmps4kType) + if (!Global.ControlSystemIsDmps4k3xxType) { //Recall startup volume for main volume level as DMPS3(non-4K) presets don't affect the main volume RecallStartupVolume(); diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs index 17aa1b1d..a3092f71 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs @@ -386,7 +386,8 @@ namespace PepperDash.Essentials.DM if (Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmOutput || Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmOutputBackend || Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutput || - Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutputBackend) + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3HdmiOutputBackend || + Dmps.SwitcherOutputs[ioSlot].CardInputOutputType == eCardInputOutputType.Dmps3DmHdmiAudioOutput) { OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputVideoNames.JoinNumber + ioSlotJoin]); OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); From 49e44ec85047faa90b75a26285ef32a114339a72 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 10 Aug 2022 15:49:41 -0500 Subject: [PATCH 12/30] fix: updated VideoCodecBase UpdateDirectoryXSig to handle directory results that are greater than 1023, XSig maximimum index --- .../VideoCodec/VideoCodecBase.cs | 30 ++++++++++++------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 5 ++-- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 593472e9..d07d5f81 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1180,31 +1180,39 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) { - var contactIndex = 1; - var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count]; + var xSigMaxIndex = 1023; + var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex + ? xSigMaxIndex + : directory.CurrentDirectoryResults.Count]; - Debug.Console(2, this, "Is root {0} Directory Count: {1}", isRoot, directory.CurrentDirectoryResults.Count); + Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot, directory.CurrentDirectoryResults.Count, tokenArray.Length); - foreach (var entry in directory.CurrentDirectoryResults) + var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex + ? directory.CurrentDirectoryResults.Take(xSigMaxIndex) + : directory.CurrentDirectoryResults; + + var counterIndex = 1; + foreach (var entry in contacts) { - var arrayIndex = contactIndex - 1; + var arrayIndex = counterIndex - 1; + var entryIndex = counterIndex; - Debug.Console(2, this, "Entry Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId); + Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId, entryIndex); if (entry is DirectoryFolder && entry.ParentFolderId == "root") { - tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, String.Format("[+] {0}", entry.Name)); + tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name)); - contactIndex++; + counterIndex++; continue; } - tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name); + tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name); - contactIndex++; + counterIndex++; } - + return GetXSigString(tokenArray); } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 73c1e8c5..6ba1082f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2730,6 +2730,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom Debug.Console(2, this, "OnDirectoryResultReturned. Result has {0} contacts", result.Contacts.Count); var directoryResult = result; + var directoryIsRoot = CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false; // If result is Root, create a copy and filter out contacts whose parent folder is not root //if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) @@ -2747,7 +2748,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom //} Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0} Contact Count: {1}", - !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue, directoryResult.Contacts.Count); + directoryIsRoot, directoryResult.Contacts.Count); // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology var handler = DirectoryResultReturned; @@ -2756,7 +2757,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom handler(this, new DirectoryEventArgs { Directory = directoryResult, - DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue + DirectoryIsOnRoot = directoryIsRoot }); } From c446c3a976e9719190921ec2e8cb6e731a3100dd Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 10 Aug 2022 17:12:30 -0500 Subject: [PATCH 13/30] fix: updates to resolve directory display issues on touch panel when bridged --- .../VideoCodec/VideoCodecBase.cs | 19 ++++++++++++------- .../VideoCodec/ZoomRoom/ZoomRoom.cs | 4 +++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index d07d5f81..6e577c59 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharp.Reflection; using Crestron.SimplSharp.Ssh; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharp; @@ -1010,7 +1011,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.DirectoryEntries.JoinNumber, Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length); @@ -1025,7 +1026,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.DirectoryEntries.JoinNumber, Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(args.Directory, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + var directoryXSig = UpdateDirectoryXSig(args.Directory, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length); @@ -1036,10 +1037,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC"); UpdateDirectoryXSig(codec.CurrentDirectoryResult, - !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); + codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); }; } @@ -1190,16 +1190,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex ? directory.CurrentDirectoryResults.Take(xSigMaxIndex) : directory.CurrentDirectoryResults; + + var contactsToDisplay = isRoot + ? contacts.Where(c => c.ParentFolderId == "root") + : contacts.Where(c => c.ParentFolderId != "root"); var counterIndex = 1; - foreach (var entry in contacts) + foreach (var entry in contactsToDisplay) { var arrayIndex = counterIndex - 1; var entryIndex = counterIndex; - Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId, entryIndex); + Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}, Type: {3}, ParentFolderId: {4}", + entry.Name, entry.FolderId, entryIndex, entry.GetType().GetCType().FullName, entry.ParentFolderId); - if (entry is DirectoryFolder && entry.ParentFolderId == "root") + if (entry is DirectoryFolder) { tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name)); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 6ba1082f..32415d1d 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -2729,6 +2729,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom { Debug.Console(2, this, "OnDirectoryResultReturned. Result has {0} contacts", result.Contacts.Count); + CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + var directoryResult = result; var directoryIsRoot = CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false; @@ -2761,7 +2763,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom }); } - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + } catch (Exception e) { From ed335cc9aeea8a81e939b31d111ac1fa7ea8df44 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Fri, 12 Aug 2022 09:26:09 -0400 Subject: [PATCH 14/30] Fixes for offline feedback for DM endpoints that don't provide offline feedback in the hardware definition. Adds offline and name feedback to joinMap for these devices. --- .../Crestron/CrestronGenericBaseDevice.cs | 2 +- .../Receivers/DmHdBaseTEndpointController.cs | 30 ++++++++++- .../Receivers/DmRmc4k100C1GController.cs | 34 ++++++++++-- .../Endpoints/Receivers/DmRmcHelper.cs | 30 +++++------ .../Transmitters/DmTx4k100Controller.cs | 34 ++++++++---- .../Endpoints/Transmitters/DmTxHelpers.cs | 54 ++++++++++--------- .../Transmitters/HDBaseTTxController.cs | 24 ++++++++- 7 files changed, 149 insertions(+), 59 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs index f4d13d4e..32407ba3 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs @@ -20,7 +20,7 @@ namespace PepperDash.Essentials.Core /// public FeedbackCollection Feedbacks { get; private set; } - public BoolFeedback IsOnline { get; set; } + public BoolFeedback IsOnline { get; private set; } public BoolFeedback IsRegistered { get; private set; } public StringFeedback IpConnectionsText { get; private set; } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs index 3af4f0fe..ec3553a1 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs @@ -1,8 +1,10 @@ -using Crestron.SimplSharp.Ssh; +using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DM.Endpoints.Receivers; - +using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core; +using PepperDash.Core; +using Newtonsoft.Json; namespace PepperDash.Essentials.DM { @@ -28,6 +30,30 @@ namespace PepperDash.Essentials.DM OutputPorts = new RoutingPortCollection {HDBaseTSink}; } + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new DmRmcControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; + } + #region IComPorts Members public CrestronCollection ComPorts { get { return Rmc.ComPorts; } } public int NumberOfComPorts { get { return Rmc.NumberOfComPorts; } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4k100C1GController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4k100C1GController.cs index 92af7ce1..529f740a 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4k100C1GController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4k100C1GController.cs @@ -1,9 +1,11 @@ using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DM; -using Crestron.SimplSharpPro.DM.Endpoints.Receivers; - -using PepperDash.Essentials.Core; - +using Crestron.SimplSharpPro.DM.Endpoints.Receivers; +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core; +using PepperDash.Core; +using Newtonsoft.Json; namespace PepperDash.Essentials.DM { @@ -31,6 +33,30 @@ namespace PepperDash.Essentials.DM InputPorts = new RoutingPortCollection {DmIn}; OutputPorts = new RoutingPortCollection {HdmiOut}; + } + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new DmRmcControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; } #region IIROutputPorts Members diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs index ced21918..5d644a2a 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs @@ -188,7 +188,7 @@ namespace PepperDash.Essentials.DM #endregion } - public abstract class DmHdBaseTControllerBase : CrestronGenericBaseDevice + public abstract class DmHdBaseTControllerBase : CrestronGenericBridgeableBaseDevice { protected HDBaseTBase Rmc; @@ -342,12 +342,12 @@ namespace PepperDash.Essentials.DM return null; } // Must use different constructor for DMPS4K types. No IPID - if (Global.ControlSystemIsDmps4kType) + if (Global.ControlSystemIsDmps4kType || typeName == "hdbasetrx" || typeName == "dmrmc4k100c1g") { var rmc = GetDmRmcControllerForDmps4k(key, name, typeName, dmps, props.ParentOutputNumber); Debug.Console(0, "DM endpoint output {0} is for Dmps4k, changing online feedback to chassis", num); - rmc.IsOnline = dmps.OutputEndpointOnlineFeedbacks[num]; - rmc.IsOnline.OutputChange += (currentDevice, args) => + rmc.IsOnline.SetValueFunc(() => dmps.OutputEndpointOnlineFeedbacks[num].BoolValue); + dmps.OutputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => { foreach (var feedback in rmc.Feedbacks) { @@ -380,19 +380,20 @@ namespace PepperDash.Essentials.DM if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) + chassis is DmMd128x128 || chassis is DmMd64x64 + || typeName == "hdbasetrx" || typeName == "dmrmc4k100c1g") { var rmc = GetDmRmcControllerForCpu3Chassis(key, name, typeName, chassis, num, parentDev); Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); - rmc.IsOnline = controller.OutputEndpointOnlineFeedbacks[num]; - rmc.IsOnline.OutputChange += (currentDevice, args) => - { - foreach (var feedback in rmc.Feedbacks) + rmc.IsOnline.SetValueFunc(() => controller.OutputEndpointOnlineFeedbacks[num].BoolValue); + controller.OutputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => { - if (feedback != null) - feedback.FireUpdate(); - } - }; + foreach (var feedback in rmc.Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } + }; return rmc; } return GetDmRmcControllerForCpu2Chassis(key, name, typeName, ipid, chassis, num, parentDev); @@ -521,8 +522,7 @@ namespace PepperDash.Essentials.DM var props = JsonConvert.DeserializeObject (dc.Properties.ToString()); - return DmRmcHelper.GetDmRmcController(dc.Key, dc.Name, type, props); - + return DmRmcHelper.GetDmRmcController(dc.Key, dc.Name, type, props); } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k100Controller.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k100Controller.cs index d2a9f7bc..5bbf5fd5 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k100Controller.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k100Controller.cs @@ -6,6 +6,7 @@ using Crestron.SimplSharpPro.DM.Endpoints.Transmitters; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; +using Newtonsoft.Json; namespace PepperDash.Essentials.DM { @@ -20,14 +21,6 @@ namespace PepperDash.Essentials.DM public RoutingInputPort HdmiIn { get; private set; } public RoutingOutputPort DmOut { get; private set; } - //public IntFeedback VideoSourceNumericFeedback { get; protected set; } - //public IntFeedback AudioSourceNumericFeedback { get; protected set; } - //public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; } - //public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; } - - //public override IntFeedback HdcpSupportAllFeedback { get; protected set; } - //public override ushort HdcpSupportCapability { get; protected set; } - /// /// Helps get the "real" inputs, including when in Auto /// @@ -70,11 +63,34 @@ namespace PepperDash.Essentials.DM HdmiIn.Port = Tx; PreventRegistration = true; + + var parentDev = DeviceManager.GetDeviceForKey(key); + var num = tx.DMInputOutput.Number; + if (parentDev is DmpsRoutingController) + { + var dmps = parentDev as DmpsRoutingController; + IsOnline.SetValueFunc(() => dmps.InputEndpointOnlineFeedbacks[num].BoolValue); + dmps.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); + controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } } public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - Debug.Console(1, this, "No properties to link. Skipping device {0}", Name); + var joinMap = new HDBaseTTxControllerJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + this.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; } #region IIROutputPorts Members diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs index 4883849e..d04f462c 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs @@ -221,37 +221,39 @@ namespace PepperDash.Essentials.DM protected DmTxControllerBase(string key, string name, EndpointTransmitterBase hardware) : base(key, name, hardware) { - // if wired to a chassis or DMPS, skip registration step in base class - if (hardware.DMInput != null || (Global.ControlSystemIsDmpsType && hardware.DMInput != null)) - { - this.PreventRegistration = true; - } - AddToFeedbackList(ActiveVideoInputFeedback); - var parentDev = DeviceManager.GetDeviceForKey(key); - var num = hardware.DMInput.Number; - - //If Dmps4K, change online feedback to chassis, tx feedback does not work - if (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType) + // if wired to a chassis or DMPS, skip registration step in base class + if (hardware.DMInput != null) { - var dmps = parentDev as DmpsRoutingController; - Debug.Console(0, "DM endpoint input {0} is for Dmps4k, changing online feedback to chassis", num); - IsOnline = dmps.InputEndpointOnlineFeedbacks[num]; - } - //If Cpu3 Chassis, change online feedback to chassis, tx feedback does not work - else if (parentDev is DmChassisController) - { - var controller = parentDev as DmChassisController; - var chassis = controller.Chassis; + this.PreventRegistration = true; - if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || - chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || - chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) + var parentDev = DeviceManager.GetDeviceForKey(key); + var num = hardware.DMInput.Number; + + //If Dmps4K, change online feedback to chassis, tx feedback does not work + if (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType) { - Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); - IsOnline = controller.InputEndpointOnlineFeedbacks[num]; + var dmps = parentDev as DmpsRoutingController; + Debug.Console(0, "DM endpoint input {0} is for Dmps4k, changing online feedback to chassis", num); + IsOnline.SetValueFunc(() => dmps.InputEndpointOnlineFeedbacks[num].BoolValue); + dmps.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } + //If Cpu3 Chassis, change online feedback to chassis, tx feedback does not work + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + var chassis = controller.Chassis; + + if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || + chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || + chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || + chassis is DmMd128x128 || chassis is DmMd64x64) + { + Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); + IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); + controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } } } diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs index 800da2a9..d7a78237 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs @@ -6,6 +6,7 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM.Endpoints.Transmitters; +using Crestron.SimplSharpPro.DM; using Newtonsoft.Json; using PepperDash.Core; @@ -18,7 +19,7 @@ namespace PepperDash.Essentials.DM /// Controller class for suitable for HDBaseT transmitters /// [Description("Wrapper Class for HDBaseT devices based on HDTx3CB class")] - public class HDBaseTTxController: BasicDmTxControllerBase, IRoutingInputsOutputs, IComPorts + public class HDBaseTTxController : BasicDmTxControllerBase, IRoutingInputsOutputs, IComPorts { public RoutingInputPort HdmiIn { get; private set; } public RoutingOutputPort DmOut { get; private set; } @@ -34,6 +35,21 @@ namespace PepperDash.Essentials.DM InputPorts = new RoutingPortCollection { HdmiIn }; OutputPorts = new RoutingPortCollection { DmOut }; + + var parentDev = DeviceManager.GetDeviceForKey(key); + var num = tx.DMInputOutput.Number; + if (parentDev is DmpsRoutingController) + { + var dmps = parentDev as DmpsRoutingController; + IsOnline.SetValueFunc(() => dmps.InputEndpointOnlineFeedbacks[num].BoolValue); + dmps.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } + else if (parentDev is DmChassisController) + { + var controller = parentDev as DmChassisController; + IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); + controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); + } } #region IRoutingInputs Members @@ -79,7 +95,7 @@ namespace PepperDash.Essentials.DM Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); this.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = this.Name; } #endregion @@ -100,6 +116,10 @@ namespace PepperDash.Essentials.DM JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "DM Tx Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); /// /// Plugin device BridgeJoinMap constructor From 139ecc3e583c2fdddb0296012c11de8c2814806e Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 12 Aug 2022 17:32:54 -0500 Subject: [PATCH 15/30] fix: (wip) updated VideoCodecBase LinkToApis to resolve issue #983 with call status and directory not updating wtih bridge online status change --- .../VideoCodec/VideoCodecBase.cs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index f9da46a5..12727c46 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -463,10 +463,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } SharingContentIsOnFeedback.FireUpdate(); - - trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); - - trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); }; } @@ -1042,9 +1038,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (!args.DeviceOnLine) return; - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC"); - UpdateDirectoryXSig(codec.CurrentDirectoryResult, - codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + // TODO [ ] #981 + var clearBytes = XSigHelpers.ClearOutputs(); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); }; } @@ -1260,7 +1259,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }); } - trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); + // TODO [ ] #983 + //trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); CallStatusChange += (sender, args) => { @@ -1364,9 +1364,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 + // TODO [ ] #983 + Debug.Console(0, this, "LinkVideoCodecCallControlsToApi: device is {0}, IsInCall {1}", args.DeviceOnLine ? "online" : "offline", IsInCall); + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC"); - UpdateCallStatusXSig(); + trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); }; } From 12248c6393d752a43df8492448b87e322f0bc868 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 12 Aug 2022 17:36:38 -0500 Subject: [PATCH 16/30] fix: removed extra debug statements --- .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index 12727c46..bf7fe188 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -1038,7 +1038,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (!args.DeviceOnLine) return; - // TODO [ ] #981 var clearBytes = XSigHelpers.ClearOutputs(); trilist.SetString(joinMap.DirectoryEntries.JoinNumber, Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); @@ -1259,8 +1258,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }); } - // TODO [ ] #983 - //trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); CallStatusChange += (sender, args) => { From 0376943dac8fec4094fca5c0aca63b9b70ac0143 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Sat, 20 Aug 2022 15:18:39 -0400 Subject: [PATCH 17/30] Reworks the creation process for DM transmitters --- .../Transmitters/DmTx200Controller.cs | 3 +- .../Transmitters/DmTx201CController.cs | 5 +- .../Transmitters/DmTx201SController.cs | 3 +- .../Transmitters/DmTx401CController.cs | 3 +- .../Transmitters/DmTx4k202CController.cs | 3 +- .../Transmitters/DmTx4k302CController.cs | 7 +- .../Transmitters/DmTx4kz202CController.cs | 3 +- .../Transmitters/DmTx4kz302CController.cs | 3 +- .../Endpoints/Transmitters/DmTxHelpers.cs | 231 +++++++++--------- .../Transmitters/HDBaseTTxController.cs | 2 + 10 files changed, 135 insertions(+), 128 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs index c638ecb6..fe4454b9 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs @@ -97,10 +97,11 @@ namespace PepperDash.Essentials.DM /// /// /// - public DmTx200Controller(string key, string name, DmTx200C2G tx) + public DmTx200Controller(string key, string name, DmTx200C2G tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs index 623391dc..660d2fec 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs @@ -99,11 +99,12 @@ namespace PepperDash.Essentials.DM /// /// /// - /// - public DmTx201CController(string key, string name, DmTx201C tx) + /// + public DmTx201CController(string key, string name, DmTx201C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs index 7c4b0d34..e42ecb4b 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs @@ -102,10 +102,11 @@ namespace PepperDash.Essentials.DM /// /// /// - public DmTx201SController(string key, string name, DmTx201S tx) + public DmTx201SController(string key, string name, DmTx201S tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs index 1407b70e..ae4e2c31 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs @@ -111,10 +111,11 @@ namespace PepperDash.Essentials.DM /// /// /// - public DmTx401CController(string key, string name, DmTx401C tx) + public DmTx401CController(string key, string name, DmTx401C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiIn = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.HDMI, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs index 729744b9..387562e4 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs @@ -96,10 +96,11 @@ namespace PepperDash.Essentials.DM } } - public DmTx4k202CController(string key, string name, DmTx4k202C tx) + public DmTx4k202CController(string key, string name, DmTx4k202C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs index 3e716f60..87906735 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs @@ -101,11 +101,12 @@ namespace PepperDash.Essentials.DM { return new RoutingPortCollection { DmOut, HdmiLoopOut }; } - } - public DmTx4k302CController(string key, string name, DmTx4k302C tx) + } + public DmTx4k302CController(string key, string name, DmTx4k302C tx, bool preventRegistration) : base(key, name, tx) { - Tx = tx; + Tx = tx; + PreventRegistration = preventRegistration; HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs index a241d60d..b9f521c6 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs @@ -86,10 +86,11 @@ namespace PepperDash.Essentials.DM return new RoutingPortCollection { DmOut, HdmiLoopOut }; } } - public DmTx4kz202CController(string key, string name, DmTx4kz202C tx) + public DmTx4kz202CController(string key, string name, DmTx4kz202C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs index 70df8259..de60d80e 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs @@ -91,10 +91,11 @@ namespace PepperDash.Essentials.DM return new RoutingPortCollection { DmOut, HdmiLoopOut }; } } - public DmTx4kz302CController(string key, string name, DmTx4kz302C tx) + public DmTx4kz302CController(string key, string name, DmTx4kz302C tx, bool preventRegistration) : base(key, name, tx) { Tx = tx; + PreventRegistration = preventRegistration; HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this, diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs index d04f462c..d707ebd3 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTxHelpers.cs @@ -20,6 +20,63 @@ namespace PepperDash.Essentials.DM { public class DmTxHelper { + + public static BasicDmTxControllerBase GetDmTxForChassisWithoutIpId(string key, string name, string typeName, DMInput dmInput) + { + if (typeName.StartsWith("dmtx200")) + return new DmTx200Controller(key, name, new DmTx200C2G(dmInput), true); + if (typeName.StartsWith("dmtx201c")) + return new DmTx201CController(key, name, new DmTx201C(dmInput), true); + if (typeName.StartsWith("dmtx201s")) + return new DmTx201SController(key, name, new DmTx201S(dmInput), true); + if (typeName.StartsWith("dmtx4k100")) + return new DmTx4k100Controller(key, name, new DmTx4K100C1G(dmInput)); + if (typeName.StartsWith("dmtx4kz100")) + return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(dmInput)); + if (typeName.StartsWith("dmtx4k202")) + return new DmTx4k202CController(key, name, new DmTx4k202C(dmInput), true); + if (typeName.StartsWith("dmtx4kz202")) + return new DmTx4kz202CController(key, name, new DmTx4kz202C(dmInput), true); + if (typeName.StartsWith("dmtx4k302")) + return new DmTx4k302CController(key, name, new DmTx4k302C(dmInput), true); + if (typeName.StartsWith("dmtx4kz302")) + return new DmTx4kz302CController(key, name, new DmTx4kz302C(dmInput), true); + if (typeName.StartsWith("dmtx401")) + return new DmTx401CController(key, name, new DmTx401C(dmInput), true); + if (typeName.StartsWith("hdbasettx")) + new HDBaseTTxController(key, name, new HDTx3CB(dmInput)); + + return null; + } + + public static BasicDmTxControllerBase GetDmTxForChassisWithIpId(string key, string name, string typeName, uint ipid, DMInput dmInput) + { + if (typeName.StartsWith("dmtx200")) + return new DmTx200Controller(key, name, new DmTx200C2G(ipid, dmInput), true); + if (typeName.StartsWith("dmtx201c")) + return new DmTx201CController(key, name, new DmTx201C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx201s")) + return new DmTx201SController(key, name, new DmTx201S(ipid, dmInput), true); + if (typeName.StartsWith("dmtx4k100")) + return new DmTx4k100Controller(key, name, new DmTx4K100C1G(ipid, dmInput)); + if (typeName.StartsWith("dmtx4kz100")) + return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(ipid, dmInput)); + if (typeName.StartsWith("dmtx4k202")) + return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx4kz202")) + return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx4k302")) + return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx4kz302")) + return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, dmInput), true); + if (typeName.StartsWith("dmtx401")) + return new DmTx401CController(key, name, new DmTx401C(ipid, dmInput), true); + if (typeName.StartsWith("hdbasettx")) + return new HDBaseTTxController(key, name, new HDTx3CB(ipid, dmInput)); + + return null; + } + /// /// A factory method for various DmTxControllers /// @@ -27,7 +84,7 @@ namespace PepperDash.Essentials.DM /// /// /// - public static BasicDmTxControllerBase GetDmTxController(string key, string name, string typeName, DmTxPropertiesConfig props) + public static BasicDmTxControllerBase GetDmTxController(string key, string name, string typeName, DmTxPropertiesConfig props) { // switch on type name... later... @@ -42,23 +99,21 @@ namespace PepperDash.Essentials.DM try { if(typeName.StartsWith("dmtx200")) - return new DmTx200Controller(key, name, new DmTx200C2G(ipid, Global.ControlSystem)); - if (typeName.StartsWith("dmtx4kz100")) - return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(ipid, Global.ControlSystem)); + return new DmTx200Controller(key, name, new DmTx200C2G(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx201c")) - return new DmTx201CController(key, name, new DmTx201C(ipid, Global.ControlSystem)); + return new DmTx201CController(key, name, new DmTx201C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx201s")) - return new DmTx201SController(key, name, new DmTx201S(ipid, Global.ControlSystem)); + return new DmTx201SController(key, name, new DmTx201S(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4k202")) - return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, Global.ControlSystem)); + return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4kz202")) - return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, Global.ControlSystem)); + return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4k302")) - return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, Global.ControlSystem)); + return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4kz302")) - return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, Global.ControlSystem)); + return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx401")) - return new DmTx401CController(key, name, new DmTx401C(ipid, Global.ControlSystem)); + return new DmTx401CController(key, name, new DmTx401C(ipid, Global.ControlSystem), false); Debug.Console(0, "{1} WARNING: Cannot create DM-TX of type: '{0}'", typeName, key); } catch (Exception e) @@ -70,12 +125,12 @@ namespace PepperDash.Essentials.DM var parentDev = DeviceManager.GetDeviceForKey(pKey); DMInput dmInput; - bool isCpu3 = false; + BasicDmTxControllerBase tx; - if (parentDev is IDmSwitch) + if (parentDev is DmChassisController) { // Get the Crestron chassis and link stuff up - var switchDev = (parentDev as IDmSwitch); + var switchDev = (parentDev as DmChassisController); var chassis = switchDev.Chassis; //Check that the input is within range of this chassis' possible inputs @@ -90,15 +145,31 @@ namespace PepperDash.Essentials.DM switchDev.TxDictionary.Add(num, key); dmInput = chassis.Inputs[num]; - //Determine if IpId is needed for this chassis type - if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || - chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || - chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) - { - isCpu3 = true; - } + try + { + //Determine if IpId is needed for this chassis type + if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || + chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || + chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || + chassis is DmMd128x128 || chassis is DmMd64x64) + { + tx = GetDmTxForChassisWithoutIpId(key, name, typeName, dmInput); + Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); + tx.IsOnline.SetValueFunc(() => switchDev.InputEndpointOnlineFeedbacks[num].BoolValue); + switchDev.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => tx.IsOnline.FireUpdate(); + return tx; + } + else + { + return GetDmTxForChassisWithIpId(key, name, typeName, ipid, dmInput); + } + } + catch (Exception e) + { + Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device for chassis: {1}", key, e); + return null; + } } else if(parentDev is DmpsRoutingController) { @@ -126,6 +197,27 @@ namespace PepperDash.Essentials.DM Debug.Console(0, "Cannot create DMPS device '{0}'. Input number '{1}' is not a DM input", key, num); return null; } + + try + { + if(Global.ControlSystemIsDmps4kType) + { + tx = GetDmTxForChassisWithoutIpId(key, name, typeName, dmInput); + Debug.Console(0, "DM endpoint output {0} is for DMPS3-4K, changing online feedback to chassis", num); + tx.IsOnline.SetValueFunc(() => dmpsDev.InputEndpointOnlineFeedbacks[num].BoolValue); + dmpsDev.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => tx.IsOnline.FireUpdate(); + return tx; + } + else + { + return GetDmTxForChassisWithIpId(key, name, typeName, ipid, dmInput); + } + } + catch (Exception e) + { + Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device for dmps: {1}", key, e); + return null; + } } else @@ -133,67 +225,6 @@ namespace PepperDash.Essentials.DM Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a processor, DM Chassis or DMPS.", key, pKey); return null; } - - try - { - // Must use different constructor for CPU3 or DMPS3-4K types. No IPID - if (isCpu3 || (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType)) - { - if (typeName.StartsWith("dmtx200")) - return new DmTx200Controller(key, name, new DmTx200C2G(dmInput)); - if (typeName.StartsWith("dmtx201c")) - return new DmTx201CController(key, name, new DmTx201C(dmInput)); - if (typeName.StartsWith("dmtx201s")) - return new DmTx201SController(key, name, new DmTx201S(dmInput)); - if (typeName.StartsWith("dmtx4k100")) - return new DmTx4k100Controller(key, name, new DmTx4K100C1G(dmInput)); - if (typeName.StartsWith("dmtx4kz100")) - return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(dmInput)); - if (typeName.StartsWith("dmtx4k202")) - return new DmTx4k202CController(key, name, new DmTx4k202C(dmInput)); - if (typeName.StartsWith("dmtx4kz202")) - return new DmTx4kz202CController(key, name, new DmTx4kz202C(dmInput)); - if (typeName.StartsWith("dmtx4k302")) - return new DmTx4k302CController(key, name, new DmTx4k302C(dmInput)); - if (typeName.StartsWith("dmtx4kz302")) - return new DmTx4kz302CController(key, name, new DmTx4kz302C(dmInput)); - if (typeName.StartsWith("dmtx401")) - return new DmTx401CController(key, name, new DmTx401C(dmInput)); - if (typeName.StartsWith("hdbasettx")) - return new HDBaseTTxController(key, name, new HDTx3CB(dmInput)); - } - else - { - if (typeName.StartsWith("dmtx200")) - return new DmTx200Controller(key, name, new DmTx200C2G(ipid, dmInput)); - if (typeName.StartsWith("dmtx201c")) - return new DmTx201CController(key, name, new DmTx201C(ipid, dmInput)); - if (typeName.StartsWith("dmtx201s")) - return new DmTx201SController(key, name, new DmTx201S(ipid, dmInput)); - if (typeName.StartsWith("dmtx4k100")) - return new DmTx4k100Controller(key, name, new DmTx4K100C1G(ipid, dmInput)); - if (typeName.StartsWith("dmtx4kz100")) - return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(ipid, dmInput)); - if (typeName.StartsWith("dmtx4k202")) - return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, dmInput)); - if (typeName.StartsWith("dmtx4kz202")) - return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, dmInput)); - if (typeName.StartsWith("dmtx4k302")) - return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, dmInput)); - if (typeName.StartsWith("dmtx4kz302")) - return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, dmInput)); - if (typeName.StartsWith("dmtx401")) - return new DmTx401CController(key, name, new DmTx401C(ipid, dmInput)); - if (typeName.StartsWith("hdbasettx")) - return new HDBaseTTxController(key, name, new HDTx3CB(ipid, dmInput)); - } - } - catch (Exception e) - { - Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device: {1}", key, e); - } - - return null; } } @@ -223,40 +254,6 @@ namespace PepperDash.Essentials.DM { AddToFeedbackList(ActiveVideoInputFeedback); - // if wired to a chassis or DMPS, skip registration step in base class - if (hardware.DMInput != null) - { - this.PreventRegistration = true; - - var parentDev = DeviceManager.GetDeviceForKey(key); - var num = hardware.DMInput.Number; - - //If Dmps4K, change online feedback to chassis, tx feedback does not work - if (parentDev is DmpsRoutingController && Global.ControlSystemIsDmps4kType) - { - var dmps = parentDev as DmpsRoutingController; - Debug.Console(0, "DM endpoint input {0} is for Dmps4k, changing online feedback to chassis", num); - IsOnline.SetValueFunc(() => dmps.InputEndpointOnlineFeedbacks[num].BoolValue); - dmps.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); - } - //If Cpu3 Chassis, change online feedback to chassis, tx feedback does not work - else if (parentDev is DmChassisController) - { - var controller = parentDev as DmChassisController; - var chassis = controller.Chassis; - - if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || - chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || - chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64) - { - Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); - IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); - controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); - } - } - } - IsOnline.OutputChange += (currentDevice, args) => { foreach (var feedback in Feedbacks) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs index d7a78237..bedf1aad 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/HDBaseTTxController.cs @@ -27,6 +27,8 @@ namespace PepperDash.Essentials.DM public HDBaseTTxController(string key, string name, HDTx3CB tx) : base(key, name, tx) { + PreventRegistration = true; + HdmiIn = new RoutingInputPort(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this) { Port = tx }; From 68a0157fbe1ec2172a14426be3d47f1477d59c92 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 30 Aug 2022 13:57:53 -0600 Subject: [PATCH 18/30] fix: add missing interface --- .../Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs index c7f68e8b..41616d96 100644 --- a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs +++ b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs @@ -7,7 +7,7 @@ using PepperDash.Essentials.Room.Config; namespace PepperDash.Essentials { - public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay + public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls { bool ExcludeFromGlobalFunctions { get; } From 074ee190ade91ff749ef205044dddec8bd873ca2 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 30 Aug 2022 21:53:41 -0500 Subject: [PATCH 19/30] feat: added cen-io-ir-104 device and factory --- .../Crestron IO/Ir/CenIoIr104Controller.cs | 62 +++++++++++++++++++ .../PepperDash_Essentials_Core.csproj | 1 + 2 files changed, 63 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs new file mode 100644 index 00000000..413f3568 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.GeneralIO; +using PepperDash.Essentials.Core.Config; + + +using PepperDash.Core; + +namespace PepperDash.Essentials.Core +{ + /// + /// Wrapper class for CEN-IO-IR-104 module + /// + [Description("Wrapper class for the CEN-IO-IR-104 module")] + public class CenIoIr104Controller : EssentialsDevice, IIROutputPorts + { + public CenIoIr104 Ir104 { get; private set; } + + public CenIoIr104Controller(string key, string name, CenIoIr104 ir104) + : base(key, name) + { + Ir104 = ir104; + } + + #region IDigitalInputPorts Members + + public CrestronCollection IROutputPorts + { + get { return Ir104.IROutputPorts; } + } + + public int NumberOfIROutputPorts + { + get { return Ir104.NumberOfIROutputPorts; } + } + + #endregion + } + + public class CenIoIr104ControllerFactory : EssentialsDeviceFactory + { + public CenIoIr104ControllerFactory() + { + TypeNames = new List() { "cenioir104" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new CEN-IR-104 Device"); + + var control = CommFactory.GetControlPropertiesConfig(dc); + var ipid = control.IpIdInt; + + return new CenIoIr104Controller(dc.Key, dc.Name, new Crestron.SimplSharpPro.GeneralIO.CenIoIr104(ipid, Global.ControlSystem)); + } + } + +} \ 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 cdf6406c..df9b8115 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -183,6 +183,7 @@ + From 122abc56e599469079467a9923266ce8252d4dd3 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 30 Aug 2022 22:02:47 -0500 Subject: [PATCH 20/30] fix: added null checks in BuildDevice with debug statements if null --- .../Crestron IO/Ir/CenIoIr104Controller.cs | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs index 413f3568..c516c03e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs @@ -16,46 +16,77 @@ namespace PepperDash.Essentials.Core /// Wrapper class for CEN-IO-IR-104 module /// [Description("Wrapper class for the CEN-IO-IR-104 module")] - public class CenIoIr104Controller : EssentialsDevice, IIROutputPorts - { - public CenIoIr104 Ir104 { get; private set; } + public class CenIoIr104Controller : EssentialsDevice, IIROutputPorts + { + private readonly CenIoIr104 _ir104; + /// + /// Constructor + /// + /// + /// + /// public CenIoIr104Controller(string key, string name, CenIoIr104 ir104) : base(key, name) { - Ir104 = ir104; + _ir104 = ir104; } #region IDigitalInputPorts Members + /// + /// IR port collection + /// public CrestronCollection IROutputPorts { - get { return Ir104.IROutputPorts; } + get { return _ir104.IROutputPorts; } } + /// + /// Number of relay ports property + /// public int NumberOfIROutputPorts { - get { return Ir104.NumberOfIROutputPorts; } + get { return _ir104.NumberOfIROutputPorts; } } #endregion } + /// + /// CEN-IO-IR-104 controller fatory + /// public class CenIoIr104ControllerFactory : EssentialsDeviceFactory { + /// + /// Constructor + /// public CenIoIr104ControllerFactory() { TypeNames = new List() { "cenioir104" }; } + /// + /// Build device CEN-IO-IR-104 + /// + /// + /// public override EssentialsDevice BuildDevice(DeviceConfig dc) { - Debug.Console(1, "Factory Attempting to create new CEN-IR-104 Device"); + Debug.Console(1, "Factory Attempting to create new CEN-IO-IR-104 Device"); + + var control = CommFactory.GetControlPropertiesConfig(dc); + if (control == null) + { + Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device"); + return null; + } - var control = CommFactory.GetControlPropertiesConfig(dc); var ipid = control.IpIdInt; - - return new CenIoIr104Controller(dc.Key, dc.Name, new Crestron.SimplSharpPro.GeneralIO.CenIoIr104(ipid, Global.ControlSystem)); + if(ipid != 0) return new CenIoIr104Controller(dc.Key, dc.Name, new CenIoIr104(ipid, Global.ControlSystem)); + + Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device using IP-ID-{0}", ipid); + return null; } } From 457494128832efb0f4aa22a9cd1977921b6c9362 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 30 Aug 2022 22:11:33 -0500 Subject: [PATCH 21/30] fix: updated debug statement for DinCenCnController class referencing building a temp sensor device --- .../Crestron IO/DinCenCn/DinCenCnController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs index 68fedc82..7e9179fe 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs @@ -34,7 +34,7 @@ namespace PepperDash.Essentials.Core public override EssentialsDevice BuildDevice(DeviceConfig dc) { - Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device"); + Debug.Console(1, "Factory Attempting to create new DIN-CEN-CN2 Device"); var control = CommFactory.GetControlPropertiesConfig(dc); var ipid = control.IpIdInt; From fb689c4484e9f95f58adb83295a75e35ace8217e Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 31 Aug 2022 14:43:58 -0500 Subject: [PATCH 22/30] fix: updated CEN-IO classes inheriting from EssentialsDevice to CrestronGenericBaseDevice to resolve activation issues --- .../Inputs/CenIoDigIn104Controller.cs | 17 ++- .../Crestron IO/Ir/CenIoIr104Controller.cs | 120 +++++++++--------- .../Crestron IO/Relay/CenIoRy104Controller.cs | 8 +- 3 files changed, 76 insertions(+), 69 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/CenIoDigIn104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/CenIoDigIn104Controller.cs index 5112f3aa..bdbcc2e9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/CenIoDigIn104Controller.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/CenIoDigIn104Controller.cs @@ -16,7 +16,7 @@ namespace PepperDash.Essentials.Core /// Wrapper class for CEN-IO-DIGIN-104 digital input module /// [Description("Wrapper class for the CEN-IO-DIGIN-104 diginal input module")] - public class CenIoDigIn104Controller : EssentialsDevice, IDigitalInputPorts + public class CenIoDigIn104Controller : CrestronGenericBaseDevice, IDigitalInputPorts { public CenIoDi104 Di104 { get; private set; } @@ -52,10 +52,17 @@ namespace PepperDash.Essentials.Core { Debug.Console(1, "Factory Attempting to create new CEN-DIGIN-104 Device"); - var control = CommFactory.GetControlPropertiesConfig(dc); - var ipid = control.IpIdInt; - - return new CenIoDigIn104Controller(dc.Key, dc.Name, new Crestron.SimplSharpPro.GeneralIO.CenIoDi104(ipid, Global.ControlSystem)); + var control = CommFactory.GetControlPropertiesConfig(dc); + if (control == null) + { + Debug.Console(1, "Factory failed to create a new CEN-DIGIN-104 Device, control properties not found"); + return null; + } + var ipid = control.IpIdInt; + if (ipid != 0) return new CenIoDigIn104Controller(dc.Key, dc.Name, new CenIoDi104(ipid, Global.ControlSystem)); + + Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device using IP-ID-{0}", ipid); + return null; } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs index c516c03e..3fa45dd7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Ir/CenIoIr104Controller.cs @@ -1,93 +1,93 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.GeneralIO; -using PepperDash.Essentials.Core.Config; - - -using PepperDash.Core; - -namespace PepperDash.Essentials.Core -{ - /// - /// Wrapper class for CEN-IO-IR-104 module - /// - [Description("Wrapper class for the CEN-IO-IR-104 module")] - public class CenIoIr104Controller : EssentialsDevice, IIROutputPorts +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.GeneralIO; +using PepperDash.Essentials.Core.Config; + + +using PepperDash.Core; + +namespace PepperDash.Essentials.Core +{ + /// + /// Wrapper class for CEN-IO-IR-104 module + /// + [Description("Wrapper class for the CEN-IO-IR-104 module")] + public class CenIoIr104Controller : CrestronGenericBaseDevice, IIROutputPorts { - private readonly CenIoIr104 _ir104; - + private readonly CenIoIr104 _ir104; + /// /// Constructor /// /// /// - /// - public CenIoIr104Controller(string key, string name, CenIoIr104 ir104) - : base(key, name) - { - _ir104 = ir104; - } - + /// + public CenIoIr104Controller(string key, string name, CenIoIr104 ir104) + : base(key, name, ir104) + { + _ir104 = ir104; + } + #region IDigitalInputPorts Members /// /// IR port collection /// - public CrestronCollection IROutputPorts - { - get { return _ir104.IROutputPorts; } + public CrestronCollection IROutputPorts + { + get { return _ir104.IROutputPorts; } } /// /// Number of relay ports property /// - public int NumberOfIROutputPorts - { - get { return _ir104.NumberOfIROutputPorts; } - } - + public int NumberOfIROutputPorts + { + get { return _ir104.NumberOfIROutputPorts; } + } + #endregion - } - + } + /// /// CEN-IO-IR-104 controller fatory - /// - public class CenIoIr104ControllerFactory : EssentialsDeviceFactory - { + /// + public class CenIoIr104ControllerFactory : EssentialsDeviceFactory + { /// /// Constructor - /// - public CenIoIr104ControllerFactory() - { - TypeNames = new List() { "cenioir104" }; - } - + /// + public CenIoIr104ControllerFactory() + { + TypeNames = new List() { "cenioir104" }; + } + /// /// Build device CEN-IO-IR-104 /// /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new CEN-IO-IR-104 Device"); - + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new CEN-IO-IR-104 Device"); + var control = CommFactory.GetControlPropertiesConfig(dc); if (control == null) { - Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device"); + Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device, control properties not found"); return null; - } - - var ipid = control.IpIdInt; + } + + var ipid = control.IpIdInt; if(ipid != 0) return new CenIoIr104Controller(dc.Key, dc.Name, new CenIoIr104(ipid, Global.ControlSystem)); Debug.Console(1, "Factory failed to create a new CEN-IO-IR-104 Device using IP-ID-{0}", ipid); - return null; - } - } - + return null; + } + } + } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/CenIoRy104Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/CenIoRy104Controller.cs index 19ca8438..e9963f4d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/CenIoRy104Controller.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/CenIoRy104Controller.cs @@ -10,7 +10,7 @@ namespace PepperDash.Essentials.Core /// Wrapper class for CEN-IO-RY-104 relay module /// [Description("Wrapper class for the CEN-IO-RY-104 relay module")] - public class CenIoRy104Controller : EssentialsDevice, IRelayPorts + public class CenIoRy104Controller : CrestronGenericBaseDevice, IRelayPorts { private readonly CenIoRy104 _ry104; @@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Core /// /// public CenIoRy104Controller(string key, string name, CenIoRy104 ry104) - : base(key, name) + : base(key, name, ry104) { _ry104 = ry104; } @@ -62,8 +62,8 @@ namespace PepperDash.Essentials.Core var controlPropertiesConfig = CommFactory.GetControlPropertiesConfig(dc); if (controlPropertiesConfig == null) - { - Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device"); + { + Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device, control properties not found"); return null; } From d7cccc0709294847c01582b29616a342d90d7d89 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Sep 2022 11:47:52 -0600 Subject: [PATCH 23/30] feat: add cooldown logic to Magic Routing In some cases, a route can be requested while a sink is cooling down. In those cases, the routing logic should keep track of requests for a destination and wait until cooling is complete to request the new route. --- .../Routing/IRoutingInputsExtensions.cs | 71 +++++++++++++++++-- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index 0c375825..4beaa37d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -11,12 +11,34 @@ using PepperDash.Core; namespace PepperDash.Essentials.Core { + public class RouteRequest + { + public IRoutingSink Destination {get; set;} + public IRoutingOutputs Source {get; set;} + public eRoutingSignalType SignalType {get; set;} + + public void HandleCooldown(object sender, FeedbackEventArgs args) + { + var coolingDevice = sender as IWarmingCooling; + + if(args.BoolValue == false) + { + Destination.ReleaseAndMakeRoute(Source, SignalType); + + if(sender == null) return; + + coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown; + } + } + } + /// /// Extensions added to any IRoutingInputs classes to provide discovery-based routing /// on those destinations. /// public static class IRoutingInputsExtensions { + private static Dictionary RouteRequests = new Dictionary(); /// /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute /// and then attempts a new Route and if sucessful, stores that RouteDescriptor @@ -24,16 +46,51 @@ namespace PepperDash.Essentials.Core /// public static void ReleaseAndMakeRoute(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) { - destination.ReleaseRoute(); + var routeRequest = new RouteRequest { + Destination = destination, + Source = source, + SignalType = signalType + }; - if (source == null) return; - var newRoute = destination.GetRouteToSource(source, signalType); - if (newRoute == null) return; - RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute); - Debug.Console(2, destination, "Executing full route"); - newRoute.ExecuteRoutes(); + var coolingDevice = destination as IWarmingCooling; + + RouteRequest existingRouteRequest; + + //We already have a route request for this device, and it's a cooling device and is cooling + if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) + { + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; + + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; + + RouteRequests[destination.Key] = routeRequest; + return; + } + + //New Request + if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) + { + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; + + RouteRequests.Add(destination.Key, routeRequest); + return; + } + + destination.ReleaseRoute(); + + RunRouteRequest(routeRequest); } + public static void RunRouteRequest(RouteRequest request) + { + if (request.Source == null) return; + var newRoute = request.Destination.GetRouteToSource(request.Source, request.SignalType); + if (newRoute == null) return; + RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute); + Debug.Console(2, request.Destination, "Executing full route"); + newRoute.ExecuteRoutes(); + } + /// /// Will release the existing route on the destination, if it is found in /// RouteDescriptorCollection.DefaultCollection From 358f44cfe598e17fc55b7fa09d3348842b206396 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Sep 2022 11:57:40 -0600 Subject: [PATCH 24/30] refactor: remove completed request from dictionary --- .../Routing/IRoutingInputsExtensions.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index 4beaa37d..2dbf895a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -58,24 +58,31 @@ namespace PepperDash.Essentials.Core //We already have a route request for this device, and it's a cooling device and is cooling if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { + { coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; RouteRequests[destination.Key] = routeRequest; return; - } + } //New Request if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) { + coolingDevice.IsCoolingDownFeedback.OutputChange -= routeRequest.HandleCooldown; + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; RouteRequests.Add(destination.Key, routeRequest); return; } + if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false) + { + RouteRequests.Remove(destination.Key); + } + destination.ReleaseRoute(); RunRouteRequest(routeRequest); From 7fe2d04d315d8e6a63e7a7914566406e2ff749cf Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Sep 2022 12:29:19 -0600 Subject: [PATCH 25/30] fix: add removal of RouteRequest when calling ReleaseRoute --- .../Routing/IRoutingInputsExtensions.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index 2dbf895a..bd5aff73 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -105,6 +105,17 @@ namespace PepperDash.Essentials.Core /// public static void ReleaseRoute(this IRoutingSink destination) { + RouteRequest existingRequest; + + if (RouteRequests.TryGetValue(destination.Key, out existingRequest) && destination is IWarmingCooling) + { + var coolingDevice = destination as IWarmingCooling; + + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown; + } + + RouteRequests.Remove(destination.Key); + var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination); if (current != null) { From c4a23e08871aaad758ffe197ec5a1498bbe47541 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 2 Sep 2022 11:19:18 -0600 Subject: [PATCH 26/30] feat(essentials): Adds RoomUiBehaviorConfig for disabling activity buttons --- .../Room/Config/EssentialsRoomConfig.cs | 9 ++++ .../Display/MockDisplay.cs | 47 +++++++++++++++---- .../Routing/IRoutingInputsExtensions.cs | 14 ++++-- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs index 5a2bd34f..b0ad2ae1 100644 --- a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs +++ b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs @@ -202,6 +202,9 @@ namespace PepperDash.Essentials.Room.Config [JsonProperty("fusion")] public EssentialsRoomFusionConfig Fusion { get; set; } + [JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)] + public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; } + [JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")] public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; } @@ -218,6 +221,12 @@ namespace PepperDash.Essentials.Room.Config } } + public class EssentialsRoomUiBehaviorConfig + { + [JsonProperty("disableActivityButtonsWhileWarmingCooling")] + public bool DisableActivityButtonsWhileWarmingCooling { get; set; } + } + public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig { [JsonProperty("defaultAudioKey")] diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs index 4ac61943..266c1cbb 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs @@ -30,11 +30,40 @@ namespace PepperDash.Essentials.Core bool _PowerIsOn; bool _IsWarmingUp; - bool _IsCoolingDown; - - protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } - protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } - protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } + bool _IsCoolingDown; + + protected override Func PowerIsOnFeedbackFunc + { + get + { + return () => + { + Debug.Console(2, this, "*************************************************** Display Power is {0}", _PowerIsOn ? "on" : "off"); + return _PowerIsOn; + }; + } } + protected override Func IsCoolingDownFeedbackFunc + { + get + { + return () => + { + Debug.Console(2, this, "*************************************************** {0}", _IsCoolingDown ? "Display is cooling down" : "Display has finished cooling down"); + return _IsCoolingDown; + }; + } + } + protected override Func IsWarmingUpFeedbackFunc + { + get + { + return () => + { + Debug.Console(2, this, "*************************************************** {0}", _IsWarmingUp ? "Display is warming up" : "Display has finished warming up"); + return _IsWarmingUp; + }; + } + } protected override Func CurrentInputFeedbackFunc { get { return () => "Not Implemented"; } } int VolumeHeldRepeatInterval = 200; @@ -61,7 +90,7 @@ namespace PepperDash.Essentials.Core MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted); WarmupTime = 10000; - CooldownTime = 5000; + CooldownTime = 10000; } public override void PowerOn() @@ -88,15 +117,15 @@ namespace PepperDash.Essentials.Core if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) { _IsCoolingDown = true; - _PowerIsOn = false; - PowerIsOnFeedback.InvokeFireUpdate(); IsCoolingDownFeedback.InvokeFireUpdate(); // Fake cool-down cycle CooldownTimer = new CTimer(o => { Debug.Console(2, this, "Cooldown timer ending"); _IsCoolingDown = false; - IsCoolingDownFeedback.InvokeFireUpdate(); + IsCoolingDownFeedback.InvokeFireUpdate(); + _PowerIsOn = false; + PowerIsOnFeedback.InvokeFireUpdate(); }, CooldownTime); } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index bd5aff73..d371c2d6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -58,12 +58,15 @@ namespace PepperDash.Essentials.Core //We already have a route request for this device, and it's a cooling device and is cooling if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { + { coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - RouteRequests[destination.Key] = routeRequest; + RouteRequests[destination.Key] = routeRequest; + + Debug.Console(2, "******************************************************** Device: {0} is cooling down and already has a routing request stored. Storing new route request to route to source key: {1}", destination.Key, routeRequest.Source.Key); + return; } @@ -74,13 +77,16 @@ namespace PepperDash.Essentials.Core coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - RouteRequests.Add(destination.Key, routeRequest); + RouteRequests.Add(destination.Key, routeRequest); + + Debug.Console(2, "******************************************************** Device: {0} is cooling down. Storing route request to route to source key: {1}", destination.Key, routeRequest.Source.Key); return; } if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false) { - RouteRequests.Remove(destination.Key); + RouteRequests.Remove(destination.Key); + Debug.Console(2, "******************************************************** Device: {0} is NOT cooling down. Removing stored route request and routing to source key: {1}", destination.Key, routeRequest.Source.Key); } destination.ReleaseRoute(); From d01be57f814ad69f7b1456f3da8b556c5881c757 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 2 Sep 2022 13:54:34 -0600 Subject: [PATCH 27/30] feat: add TouchpanelBase class and initial implementation --- .../UI/EssentialsTouchpanelController.cs | 199 +------------ .../PepperDash_Essentials_Core.csproj | 1 + .../UI/TouchpanelBase.cs | 270 ++++++++++++++++++ 3 files changed, 278 insertions(+), 192 deletions(-) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 441381bd..24bc33db 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -11,10 +11,11 @@ using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.PageManagers; +using PepperDash.Essentials.Core.UI; namespace PepperDash.Essentials { - public class EssentialsTouchpanelController : EssentialsDevice, IHasBasicTriListWithSmartObject + public class EssentialsTouchpanelController : TouchpanelBase { private CrestronTouchpanelPropertiesConfig _propertiesConfig; @@ -26,189 +27,29 @@ namespace PepperDash.Essentials public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw, string projectName, string sgdPath) - : base(key, name) + : base(key, name, tsw, sgdPath) { - Panel = tsw; - - if (!string.IsNullOrEmpty(sgdPath)) - Panel.LoadSmartObjects(sgdPath); - else - Debug.Console(1, this, "No SGD file path defined"); - - - - tsw.SigChange += Panel_SigChange; } public EssentialsTouchpanelController(string key, string name, Dge100 dge, string projectName, string sgdPath) - : base(key, name) + : base(key, name, dge, sgdPath) { - Panel = dge; - - if (!string.IsNullOrEmpty(sgdPath)) - Panel.LoadSmartObjects(sgdPath); - else - Debug.Console(1, this, "No SGD file path defined"); - - dge.SigChange += Panel_SigChange; } /// /// Config constructor /// public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id) - : base(key, name) + : base(key, name, type, props, id) { - _propertiesConfig = props; - - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware..."); - type = type.ToLower(); - try - { - if (type == "crestronapp") - { - var app = new CrestronApp(id, Global.ControlSystem); - app.ParameterProjectName.Value = props.ProjectName; - Panel = app; - } - else if (type == "xpanel") - Panel = new XpanelForSmartGraphics(id, Global.ControlSystem); - else if (type == "tsw550") - Panel = new Tsw550(id, Global.ControlSystem); - else if (type == "tsw552") - Panel = new Tsw552(id, Global.ControlSystem); - else if (type == "tsw560") - Panel = new Tsw560(id, Global.ControlSystem); - else if (type == "tsw750") - Panel = new Tsw750(id, Global.ControlSystem); - else if (type == "tsw752") - Panel = new Tsw752(id, Global.ControlSystem); - else if (type == "tsw760") - Panel = new Tsw760(id, Global.ControlSystem); - else if (type == "tsw1050") - Panel = new Tsw1050(id, Global.ControlSystem); - else if (type == "tsw1052") - Panel = new Tsw1052(id, Global.ControlSystem); - else if (type == "tsw1060") - Panel = new Tsw1060(id, Global.ControlSystem); - else if (type == "tsw570") - Panel = new Tsw570(id, Global.ControlSystem); - else if (type == "tsw770") - Panel = new Tsw770(id, Global.ControlSystem); - else if (type == "ts770") - Panel = new Ts770(id, Global.ControlSystem); - else if (type == "tsw1070") - Panel = new Tsw1070(id, Global.ControlSystem); - else if (type == "ts1070") - Panel = new Ts1070(id, Global.ControlSystem); - else - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type); - return; - } - } - catch (Exception e) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); - return; - } - - // Reserved sigs - if (Panel is TswFt5ButtonSystem) - { - var tsw = Panel as TswFt5ButtonSystem; - tsw.ExtenderSystemReservedSigs.Use(); - tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange - += ExtenderSystemReservedSigs_DeviceExtenderSigChange; - - tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange); - - } - - if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success) - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason); - - // Give up cleanly if SGD is not present. - var sgdName = Global.FilePathPrefix + "sgd" + Global.DirectorySeparator + props.SgdFile; - if (!File.Exists(sgdName)) - { - Debug.Console(0, this, "Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName); - - sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + props.SgdFile; - - if (!File.Exists(sgdName)) - { - Debug.Console(0, this, "Unable to find SGD file '{0}' in User sgd or application SGD folder. Exiting touchpanel load.", sgdName); - return; - } - } - - Panel.LoadSmartObjects(sgdName); - Panel.SigChange += Panel_SigChange; - - AddPostActivationAction(() => - { - // Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event - var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner; - - if (roomCombiner != null) - { - // Subscribe to the even - roomCombiner.RoomCombinationScenarioChanged += new EventHandler(roomCombiner_RoomCombinationScenarioChanged); - - // Connect to the initial roomKey - if (roomCombiner.CurrentScenario != null) - { - // Use the current scenario - DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); - } - else - { - // Current Scenario not yet set. Use default - SetupPanelDrivers(_propertiesConfig.DefaultRoomKey); - } - } - else - { - // No room combiner, use the default key - SetupPanelDrivers(_propertiesConfig.DefaultRoomKey); - } - }); } - void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e) - { - var roomCombiner = sender as IEssentialsRoomCombiner; - - DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); - } - - /// - /// Determines the room key to use based on the scenario - /// - /// - void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario) - { - string newRoomKey = null; - - if (scenario.UiMap.ContainsKey(Key)) - { - newRoomKey = scenario.UiMap[Key]; - } - else if (scenario.UiMap.ContainsKey(_propertiesConfig.DefaultRoomKey)) - { - newRoomKey = scenario.UiMap[_propertiesConfig.DefaultRoomKey]; - } - - SetupPanelDrivers(newRoomKey); - } - /// /// Sets up drivers and links them to the room specified /// /// key of room to link the drivers to - void SetupPanelDrivers(string roomKey) + protected override void SetupPanelDrivers(string roomKey) { // Clear out any existing actions Panel.ClearAllSigActions(); @@ -338,13 +179,7 @@ namespace PepperDash.Essentials driver.Show(); } - void HomePressed() - { - if (BacklightTransitionedOnTimer == null) - PanelDriver.BackButtonPressed(); - } - - void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) + protected override void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) { // If the sig is transitioning on, mark it in case it was home button that transitioned it var blOnSig = (Panel as TswFt5ButtonSystem).ExtenderSystemReservedSigs.BacklightOnFeedback; @@ -382,26 +217,6 @@ namespace PepperDash.Essentials act(value); } } - - void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) - { - if (Debug.Level == 2) - Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); - var uo = args.Sig.UserObject; - if (uo is Action) - (uo as Action)(args.Sig.BoolValue); - else if (uo is Action) - (uo as Action)(args.Sig.UShortValue); - else if (uo is Action) - (uo as Action)(args.Sig.StringValue); - } - - void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args) - { - var uo = args.Button.UserObject; - if(uo is Action) - (uo as Action)(args.Button.State == eButtonState.Pressed); - } } public class EssentialsTouchpanelControllerFactory : EssentialsDeviceFactory diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 9bf1f8ca..b2a3b363 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -366,6 +366,7 @@ + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs new file mode 100644 index 00000000..01409cf4 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -0,0 +1,270 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core; +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Core; +using Crestron.SimplSharpPro.UI; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharpPro; + +namespace PepperDash.Essentials.Core.UI +{ + public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmartObject + { + protected CrestronTouchpanelPropertiesConfig _config; + public BasicTriListWithSmartObject Panel { get; private set; } + + /// + /// Constructor for pre-created Panel. This constructor attempts to load the SGD file from the provided SGD path and subscribes to the + /// `SigChange` event for the provided panel. + /// + /// Essentials Device Key + /// Essentials Device Name + /// Provided TSW Panel + /// Path to SGD file + protected TouchpanelBase(string key, string name, Tswx52ButtonVoiceControl tsw, string sgdPath) + :base(key, name) + { + Panel = tsw; + + //moving loading of SGD to preactivation action...should make creation quicker + AddPreActivationAction(() => { + if(!string.IsNullOrEmpty(sgdPath)) + { + Debug.Console(1, this, "Loading sgd file from {0}", sgdPath); + Panel.LoadSmartObjects(sgdPath); + return; + } + + Debug.Console(1, this, "No SGD file path defined"); + }); + + Panel.SigChange += Panel_SigChange; + } + + /// + /// Constructor for use with DGE panels. This constructor attempts to load the provided SGD file from the provided SGD path and subscribes to the + /// `SigChange` event for the provided DGE. + /// + /// Essentials Device Key + /// Essentials Device Name + /// Provided DGE + /// Path to SGD file + protected TouchpanelBase(string key, string name, Dge100 dge, string sgdPath):base(key, name) + { + Panel = dge; + + AddPreActivationAction(() => + { + if (!string.IsNullOrEmpty(sgdPath)) + { + Debug.Console(1, this, "Loading sgd file from {0}", sgdPath); + Panel.LoadSmartObjects(sgdPath); + return; + } + + Debug.Console(1, this, "No SGD file path defined"); + }); + + Panel.SigChange += Panel_SigChange; + } + + /// + /// Constructor for use with device Factory. A touch panel device will be created based on the provided IP-ID and the + /// type of the panel. The SGD File path can be specified using the config property, or a default one located in the program directory if none + /// is provided. + /// + /// Essentials Device Key + /// Essentials Device Name + /// Touchpanel Type to build + /// Touchpanel Configuration + /// IP-ID to use for touch panel + protected TouchpanelBase(string key, string name, string type, CrestronTouchpanelPropertiesConfig config, uint id) + :base(key, name) + { + var panel = GetPanelForType(type, id); + if(panel != null) + { + Panel = panel; + } + + if (Panel is TswFt5ButtonSystem) + { + var tsw = Panel as TswFt5ButtonSystem; + tsw.ExtenderSystemReservedSigs.Use(); + tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange + += ExtenderSystemReservedSigs_DeviceExtenderSigChange; + + tsw.ButtonStateChange += Tsw_ButtonStateChange; + } + + + AddPreActivationAction(() => { + if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success) + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason); + + // Give up cleanly if SGD is not present. + var sgdName = Global.FilePathPrefix + "sgd" + Global.DirectorySeparator + _config.SgdFile; + if (!File.Exists(sgdName)) + { + Debug.Console(0, this, "Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName); + + sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + config.SgdFile; + + if (!File.Exists(sgdName)) + { + Debug.Console(0, this, "Unable to find SGD file '{0}' in User sgd or application SGD folder. Exiting touchpanel load.", sgdName); + return; + } + } + }); + + AddPostActivationAction(() => + { + // Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event + var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner; + + if (roomCombiner != null) + { + // Subscribe to the even + roomCombiner.RoomCombinationScenarioChanged += new EventHandler(roomCombiner_RoomCombinationScenarioChanged); + + // Connect to the initial roomKey + if (roomCombiner.CurrentScenario != null) + { + // Use the current scenario + DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); + } + else + { + // Current Scenario not yet set. Use default + SetupPanelDrivers(_config.DefaultRoomKey); + } + } + else + { + // No room combiner, use the default key + SetupPanelDrivers(_config.DefaultRoomKey); + } + }); + } + + /// + /// Setup Panel operation + /// + /// Room Key for this panel + protected abstract void SetupPanelDrivers(string roomKey); + + + /// + /// + /// + /// + /// + protected virtual void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e) + { + var roomCombiner = sender as IEssentialsRoomCombiner; + + DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); + } + + /// + /// Determines the room key to use based on the scenario + /// + /// + protected virtual void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario) + { + string newRoomKey = null; + + if (scenario.UiMap.ContainsKey(Key)) + { + newRoomKey = scenario.UiMap[Key]; + } + else if (scenario.UiMap.ContainsKey(_config.DefaultRoomKey)) + { + newRoomKey = scenario.UiMap[_config.DefaultRoomKey]; + } + + SetupPanelDrivers(newRoomKey); + } + + private BasicTriListWithSmartObject GetPanelForType(string type, uint id) + { + type = type.ToLower(); + try + { + if (type == "crestronapp") + { + var app = new CrestronApp(id, Global.ControlSystem); + app.ParameterProjectName.Value = _config.ProjectName; + return app; + } + else if (type == "xpanel") + return new XpanelForSmartGraphics(id, Global.ControlSystem); + else if (type == "tsw550") + return new Tsw550(id, Global.ControlSystem); + else if (type == "tsw552") + return new Tsw552(id, Global.ControlSystem); + else if (type == "tsw560") + return new Tsw560(id, Global.ControlSystem); + else if (type == "tsw750") + return new Tsw750(id, Global.ControlSystem); + else if (type == "tsw752") + return new Tsw752(id, Global.ControlSystem); + else if (type == "tsw760") + return new Tsw760(id, Global.ControlSystem); + else if (type == "tsw1050") + return new Tsw1050(id, Global.ControlSystem); + else if (type == "tsw1052") + return new Tsw1052(id, Global.ControlSystem); + else if (type == "tsw1060") + return new Tsw1060(id, Global.ControlSystem); + else if (type == "tsw570") + return new Tsw570(id, Global.ControlSystem); + else if (type == "tsw770") + return new Tsw770(id, Global.ControlSystem); + else if (type == "ts770") + return new Ts770(id, Global.ControlSystem); + else if (type == "tsw1070") + return new Tsw1070(id, Global.ControlSystem); + else if (type == "ts1070") + return new Ts1070(id, Global.ControlSystem); + else + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type); + return null; + } + } + catch (Exception e) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); + return null; + } + } + + private void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) + { + if (Debug.Level == 2) + Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); + var uo = args.Sig.UserObject; + if (uo is Action) + (uo as Action)(args.Sig.BoolValue); + else if (uo is Action) + (uo as Action)(args.Sig.UShortValue); + else if (uo is Action) + (uo as Action)(args.Sig.StringValue); + } + + private void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args) + { + var uo = args.Button.UserObject; + if(uo is Action) + (uo as Action)(args.Button.State == eButtonState.Pressed); + } + + protected abstract void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args); + } +} \ No newline at end of file From 88a16b577b46778606f88b183ef6eb667e3a9418 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 2 Sep 2022 14:35:06 -0600 Subject: [PATCH 28/30] refactor: update constructors for touchpanel controller and base class --- .../UI/EssentialsTouchpanelController.cs | 100 +++++++++++----- .../UI/TouchpanelBase.cs | 109 +----------------- 2 files changed, 77 insertions(+), 132 deletions(-) diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 24bc33db..34d5e11a 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -12,35 +12,21 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.PageManagers; using PepperDash.Essentials.Core.UI; +using Newtonsoft.Json; namespace PepperDash.Essentials { public class EssentialsTouchpanelController : TouchpanelBase - { - private CrestronTouchpanelPropertiesConfig _propertiesConfig; - - public BasicTriListWithSmartObject Panel { get; private set; } - + { public PanelDriverBase PanelDriver { get; private set; } CTimer BacklightTransitionedOnTimer; - public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw, - string projectName, string sgdPath) - : base(key, name, tsw, sgdPath) - { - } - - public EssentialsTouchpanelController(string key, string name, Dge100 dge, string projectName, string sgdPath) - : base(key, name, dge, sgdPath) - { - } - /// /// Config constructor /// - public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id) - : base(key, name, type, props, id) + public EssentialsTouchpanelController(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) + : base(key, name, panel, config) { } @@ -56,7 +42,7 @@ namespace PepperDash.Essentials Debug.Console(0, this, "Linking TP '{0}' to Room '{1}'", Key, roomKey); - var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, _propertiesConfig); + var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, _config); // Then the sub drivers // spin up different room drivers depending on room type @@ -65,15 +51,15 @@ namespace PepperDash.Essentials { // Screen Saver Driver - mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig); + mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _config); // Header Driver Debug.Console(0, this, "Adding header driver"); - mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig); + mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _config); // AV Driver Debug.Console(0, this, "Adding huddle space AV driver"); - var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, _propertiesConfig); + var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, _config); avDriver.DefaultRoomKey = roomKey; mainDriver.AvDriver = avDriver; avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom; @@ -82,7 +68,7 @@ namespace PepperDash.Essentials if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) { Debug.Console(0, this, "Adding environment driver"); - mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig); + mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _config); mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment); } @@ -111,13 +97,13 @@ namespace PepperDash.Essentials Debug.Console(0, this, "Adding huddle space VTC AV driver"); // Screen Saver Driver - mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig); + mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _config); // Header Driver - mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig); + mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _config); // AV Driver - var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, _propertiesConfig); + var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, _config); var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(Panel, avDriver, (room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver); @@ -130,7 +116,7 @@ namespace PepperDash.Essentials if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) { Debug.Console(0, this, "Adding environment driver"); - mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig); + mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _config); mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment); } @@ -229,13 +215,69 @@ namespace PepperDash.Essentials public override EssentialsDevice BuildDevice(DeviceConfig dc) { var comm = CommFactory.GetControlPropertiesConfig(dc); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + var panel = GetPanelForType(dc.Type, comm.IpIdInt, props.ProjectName); Debug.Console(1, "Factory Attempting to create new EssentialsTouchpanelController"); - var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, dc.Type, props, comm.IpIdInt); + var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, panel, props); return panelController; } + + private BasicTriListWithSmartObject GetPanelForType(string type, uint id, string projectName) + { + type = type.ToLower(); + try + { + if (type == "crestronapp") + { + var app = new CrestronApp(id, Global.ControlSystem); + app.ParameterProjectName.Value = projectName; + return app; + } + else if (type == "xpanel") + return new XpanelForSmartGraphics(id, Global.ControlSystem); + else if (type == "tsw550") + return new Tsw550(id, Global.ControlSystem); + else if (type == "tsw552") + return new Tsw552(id, Global.ControlSystem); + else if (type == "tsw560") + return new Tsw560(id, Global.ControlSystem); + else if (type == "tsw750") + return new Tsw750(id, Global.ControlSystem); + else if (type == "tsw752") + return new Tsw752(id, Global.ControlSystem); + else if (type == "tsw760") + return new Tsw760(id, Global.ControlSystem); + else if (type == "tsw1050") + return new Tsw1050(id, Global.ControlSystem); + else if (type == "tsw1052") + return new Tsw1052(id, Global.ControlSystem); + else if (type == "tsw1060") + return new Tsw1060(id, Global.ControlSystem); + else if (type == "tsw570") + return new Tsw570(id, Global.ControlSystem); + else if (type == "tsw770") + return new Tsw770(id, Global.ControlSystem); + else if (type == "ts770") + return new Ts770(id, Global.ControlSystem); + else if (type == "tsw1070") + return new Tsw1070(id, Global.ControlSystem); + else if (type == "ts1070") + return new Ts1070(id, Global.ControlSystem); + else + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type); + return null; + } + } + catch (Exception e) + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); + return null; + } + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs index 01409cf4..806431ec 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -28,49 +28,9 @@ namespace PepperDash.Essentials.Core.UI protected TouchpanelBase(string key, string name, Tswx52ButtonVoiceControl tsw, string sgdPath) :base(key, name) { - Panel = tsw; - //moving loading of SGD to preactivation action...should make creation quicker - AddPreActivationAction(() => { - if(!string.IsNullOrEmpty(sgdPath)) - { - Debug.Console(1, this, "Loading sgd file from {0}", sgdPath); - Panel.LoadSmartObjects(sgdPath); - return; - } - - Debug.Console(1, this, "No SGD file path defined"); - }); - - Panel.SigChange += Panel_SigChange; } - /// - /// Constructor for use with DGE panels. This constructor attempts to load the provided SGD file from the provided SGD path and subscribes to the - /// `SigChange` event for the provided DGE. - /// - /// Essentials Device Key - /// Essentials Device Name - /// Provided DGE - /// Path to SGD file - protected TouchpanelBase(string key, string name, Dge100 dge, string sgdPath):base(key, name) - { - Panel = dge; - - AddPreActivationAction(() => - { - if (!string.IsNullOrEmpty(sgdPath)) - { - Debug.Console(1, this, "Loading sgd file from {0}", sgdPath); - Panel.LoadSmartObjects(sgdPath); - return; - } - - Debug.Console(1, this, "No SGD file path defined"); - }); - - Panel.SigChange += Panel_SigChange; - } /// /// Constructor for use with device Factory. A touch panel device will be created based on the provided IP-ID and the @@ -82,14 +42,10 @@ namespace PepperDash.Essentials.Core.UI /// Touchpanel Type to build /// Touchpanel Configuration /// IP-ID to use for touch panel - protected TouchpanelBase(string key, string name, string type, CrestronTouchpanelPropertiesConfig config, uint id) + protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) :base(key, name) - { - var panel = GetPanelForType(type, id); - if(panel != null) - { - Panel = panel; - } + { + Panel = panel; if (Panel is TswFt5ButtonSystem) { @@ -100,7 +56,8 @@ namespace PepperDash.Essentials.Core.UI tsw.ButtonStateChange += Tsw_ButtonStateChange; } - + + _config = config; AddPreActivationAction(() => { if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success) @@ -112,7 +69,7 @@ namespace PepperDash.Essentials.Core.UI { Debug.Console(0, this, "Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName); - sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + config.SgdFile; + sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + _config.SgdFile; if (!File.Exists(sgdName)) { @@ -191,60 +148,6 @@ namespace PepperDash.Essentials.Core.UI SetupPanelDrivers(newRoomKey); } - private BasicTriListWithSmartObject GetPanelForType(string type, uint id) - { - type = type.ToLower(); - try - { - if (type == "crestronapp") - { - var app = new CrestronApp(id, Global.ControlSystem); - app.ParameterProjectName.Value = _config.ProjectName; - return app; - } - else if (type == "xpanel") - return new XpanelForSmartGraphics(id, Global.ControlSystem); - else if (type == "tsw550") - return new Tsw550(id, Global.ControlSystem); - else if (type == "tsw552") - return new Tsw552(id, Global.ControlSystem); - else if (type == "tsw560") - return new Tsw560(id, Global.ControlSystem); - else if (type == "tsw750") - return new Tsw750(id, Global.ControlSystem); - else if (type == "tsw752") - return new Tsw752(id, Global.ControlSystem); - else if (type == "tsw760") - return new Tsw760(id, Global.ControlSystem); - else if (type == "tsw1050") - return new Tsw1050(id, Global.ControlSystem); - else if (type == "tsw1052") - return new Tsw1052(id, Global.ControlSystem); - else if (type == "tsw1060") - return new Tsw1060(id, Global.ControlSystem); - else if (type == "tsw570") - return new Tsw570(id, Global.ControlSystem); - else if (type == "tsw770") - return new Tsw770(id, Global.ControlSystem); - else if (type == "ts770") - return new Ts770(id, Global.ControlSystem); - else if (type == "tsw1070") - return new Tsw1070(id, Global.ControlSystem); - else if (type == "ts1070") - return new Ts1070(id, Global.ControlSystem); - else - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type); - return null; - } - } - catch (Exception e) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); - return null; - } - } - private void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) { if (Debug.Level == 2) From 1b9f16ea744874eea21a2e9fc0ef3a590cc492f1 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 2 Sep 2022 14:44:15 -0600 Subject: [PATCH 29/30] fix: add missing event registration --- .../UI/TouchpanelBase.cs | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs index 806431ec..fbb7cd32 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -17,21 +17,6 @@ namespace PepperDash.Essentials.Core.UI protected CrestronTouchpanelPropertiesConfig _config; public BasicTriListWithSmartObject Panel { get; private set; } - /// - /// Constructor for pre-created Panel. This constructor attempts to load the SGD file from the provided SGD path and subscribes to the - /// `SigChange` event for the provided panel. - /// - /// Essentials Device Key - /// Essentials Device Name - /// Provided TSW Panel - /// Path to SGD file - protected TouchpanelBase(string key, string name, Tswx52ButtonVoiceControl tsw, string sgdPath) - :base(key, name) - { - - } - - /// /// Constructor for use with device Factory. A touch panel device will be created based on the provided IP-ID and the /// type of the panel. The SGD File path can be specified using the config property, or a default one located in the program directory if none @@ -45,7 +30,9 @@ namespace PepperDash.Essentials.Core.UI protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) :base(key, name) { - Panel = panel; + Panel = panel; + + Panel.SigChange += Panel_SigChange; if (Panel is TswFt5ButtonSystem) { @@ -116,6 +103,14 @@ namespace PepperDash.Essentials.Core.UI protected abstract void SetupPanelDrivers(string roomKey); + /// + /// Event handler for System Extender Events + /// + /// + /// + protected abstract void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args); + + /// /// /// @@ -167,7 +162,5 @@ namespace PepperDash.Essentials.Core.UI if(uo is Action) (uo as Action)(args.Button.State == eButtonState.Pressed); } - - protected abstract void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args); } } \ No newline at end of file From 9b2611be02040b1f4c7e6a02e96b12e94e056b23 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 2 Sep 2022 15:00:00 -0600 Subject: [PATCH 30/30] refactor: add error handling for cases where type isn't found --- .../UI/EssentialsTouchpanelController.cs | 5 +++++ .../PepperDashEssentialsBase/UI/TouchpanelBase.cs | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index 34d5e11a..67f25f42 100644 --- a/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -219,6 +219,11 @@ namespace PepperDash.Essentials var panel = GetPanelForType(dc.Type, comm.IpIdInt, props.ProjectName); + if (panel == null) + { + Debug.Console(0, "Unable to create Touchpanel for type {0}. Touchpanel Controller WILL NOT function correctly", dc.Type); + } + Debug.Console(1, "Factory Attempting to create new EssentialsTouchpanelController"); var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, panel, props); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs index fbb7cd32..36e0342e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/UI/TouchpanelBase.cs @@ -29,7 +29,14 @@ namespace PepperDash.Essentials.Core.UI /// IP-ID to use for touch panel protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) :base(key, name) - { + { + + if (Panel == null) + { + Debug.Console(0, this, "Panel is not valid. Touchpanel class WILL NOT work correctly"); + return; + } + Panel = panel; Panel.SigChange += Panel_SigChange;