From f5753109d59167561662b466c8b8b197fd1cc525 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 9 Nov 2020 15:14:47 -0700 Subject: [PATCH] Fixes multiple issues closes #474 closes #473 closes #470 --- .../Room/Types/EssentialsHuddleVtc1Room.cs | 6 + .../DeviceTypeInterfaces/IPower.cs | 25 +- .../Cameras/CameraBase.cs | 12 +- .../Codec/IHasExternalSourceSwitching.cs | 1 + .../Display/SamsungMDCDisplay.cs | 1322 ++++++++--------- .../SetTopBox/IRSetTopBoxBase.cs | 146 +- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 8 + 7 files changed, 785 insertions(+), 735 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 97c1775e..30a398fa 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -190,6 +190,12 @@ namespace PepperDash.Essentials (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control"); if (handler != null) handler(_CurrentSourceInfo, ChangeType.DidChange); + + var vc = VideoCodec as IHasExternalSourceSwitching; + if (vc != null) + { + vc.SetSelectedSource(_CurrentSourceInfo.SourceKey); + } } } SourceListItem _CurrentSourceInfo; diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPower.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPower.cs index a392d149..41d54159 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPower.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPower.cs @@ -14,16 +14,23 @@ using PepperDash.Essentials.Core.SmartObjects; namespace PepperDash.Essentials.Core { /// - /// + /// Defines the ability to power a device on and off /// public interface IPower { void PowerOn(); void PowerOff(); void PowerToggle(); - BoolFeedback PowerIsOnFeedback { get; } } + /// + /// Adds feedback for current power state + /// + public interface IPowerWithFeedback : IPower + { + BoolFeedback PowerIsOnFeedback { get; } + } + /// /// /// @@ -34,7 +41,12 @@ namespace PepperDash.Essentials.Core triList.SetSigFalseAction(101, dev.PowerOn); triList.SetSigFalseAction(102, dev.PowerOff); triList.SetSigFalseAction(103, dev.PowerToggle); - dev.PowerIsOnFeedback.LinkInputSig(triList.BooleanInput[101]); + + var fbdev = dev as IPowerWithFeedback; + if (fbdev != null) + { + fbdev.PowerIsOnFeedback.LinkInputSig(triList.BooleanInput[101]); + } } public static void UnlinkButtons(this IPower dev, BasicTriList triList) @@ -42,7 +54,12 @@ namespace PepperDash.Essentials.Core triList.ClearBoolSigAction(101); triList.ClearBoolSigAction(102); triList.ClearBoolSigAction(103); - dev.PowerIsOnFeedback.UnlinkInputSig(triList.BooleanInput[101]); + + var fbdev = dev as IPowerWithFeedback; + if (fbdev != null) + { + fbdev.PowerIsOnFeedback.UnlinkInputSig(triList.BooleanInput[101]); + } } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs index 35d696c7..61f23267 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs @@ -181,14 +181,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras }); } - if (cameraDevice is IPower) + var powerCamera = cameraDevice as IPower; + if (powerCamera != null) { - var powerCamera = cameraDevice as IPower; trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () => powerCamera.PowerOn()); trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () => powerCamera.PowerOff()); - powerCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]); - powerCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]); + var powerFbCamera = powerCamera as IPowerWithFeedback; + if (powerFbCamera != null) + { + powerFbCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]); + powerFbCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]); + } } if (cameraDevice is ICommunicationMonitor) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs index d86f628e..b4449d86 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs @@ -14,6 +14,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type); void SetExternalSourceState(string key, eExternalSourceMode mode); void ClearExternalSources(); + void SetSelectedSource(string key); Action RunRouteAction { set;} } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs index b8525e1e..47c08cea 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs @@ -1,668 +1,668 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro.CrestronThread; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Core.Routing; -using Feedback = PepperDash.Essentials.Core.Feedback; - -using Newtonsoft.Json.Linq; - -namespace PepperDash.Essentials.Devices.Displays -{ - /// - /// - /// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.CrestronThread; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.Routing; +using Feedback = PepperDash.Essentials.Core.Feedback; + +using Newtonsoft.Json.Linq; + +namespace PepperDash.Essentials.Devices.Displays +{ + /// + /// + /// public class SamsungMDC : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor, IInputDisplayPort1, IInputDisplayPort2, - IInputHdmi1, IInputHdmi2, IInputHdmi3, IInputHdmi4, IBridgeAdvanced - { + IInputHdmi1, IInputHdmi2, IInputHdmi3, IInputHdmi4, IBridgeAdvanced + { public IBasicCommunication Communication { get; private set; } - - - public StatusMonitorBase CommunicationMonitor { get; private set; } - - public byte ID { get; private set; } - - bool LastCommandSentWasVolume; - - bool _PowerIsOn; - bool _IsWarmingUp; - bool _IsCoolingDown; - ushort _VolumeLevelForSig; - int _LastVolumeSent; - bool _IsMuted; - RoutingInputPort _CurrentInputPort; - byte[] IncomingBuffer = new byte[]{}; - ActionIncrementer VolumeIncrementer; - bool VolumeIsRamping; - public bool IsInStandby { get; private set; } - bool IsPoweringOnIgnorePowerFb; - - protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } - protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } - protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } - protected override Func CurrentInputFeedbackFunc { get { return () => _CurrentInputPort.Key; } } - - /// - /// Constructor for IBasicCommunication - /// - public SamsungMDC(string key, string name, IBasicCommunication comm, string id) - : base(key, name) - { - Communication = comm; - Communication.BytesReceived += new EventHandler(Communication_BytesReceived); - - ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor - Init(); - } - - /// - /// Constructor for TCP - /// - public SamsungMDC(string key, string name, string hostname, int port, string id) - : base(key, name) - { - Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000); - ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor - Init(); - } - - /// - /// Constructor for COM - /// - public SamsungMDC(string key, string name, ComPort port, ComPort.ComPortSpec spec, string id) - : base(key, name) - { - Communication = new ComPortController(key + "-com", port, spec); - //Communication.TextReceived += new EventHandler(Communication_TextReceived); - - ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor - Init(); - } - - void AddRoutingInputPort(RoutingInputPort port, byte fbMatch) - { - port.FeedbackMatchObject = fbMatch; - InputPorts.Add(port); - } - - void Init() - { - WarmupTime = 10000; - CooldownTime = 8000; - - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet); - DeviceManager.AddDevice(CommunicationMonitor); - - VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80, - v => SetVolume((ushort)v), - () => _LastVolumeSent); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this), 0x21); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1PC, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1PC), this), 0x22); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this), 0x23); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2PC, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2PC), this), 0x24); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this), 0x32); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this), 0x25); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this), 0x18); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Composite, new Action(InputVideo1), this), 0x08); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn1, eRoutingSignalType.Video, - eRoutingPortConnectionType.Vga, new Action(InputRgb1), this), 0x14); - - AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn2, eRoutingSignalType.Video, - eRoutingPortConnectionType.Rgb, new Action(new Action(InputRgb2)), this), 0x1E); - - VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevelForSig; }); - MuteFeedback = new BoolFeedback(() => _IsMuted); - - StatusGet(); - } - - /// - /// - /// - /// - public override bool CustomActivate() - { - Communication.Connect(); - CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); }; - CommunicationMonitor.Start(); - return true; - } - - public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); - } - - public override FeedbackCollection Feedbacks - { - get - { - var list = base.Feedbacks; - list.AddRange(new List - { - VolumeLevelFeedback, - MuteFeedback, - CurrentInputFeedback - }); - return list; - } - } - - /// - /// / - /// - /// - void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) - { - try - { - // This is probably not thread-safe buffering - // Append the incoming bytes with whatever is in the buffer - var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length]; - IncomingBuffer.CopyTo(newBytes, 0); - e.Bytes.CopyTo(newBytes, IncomingBuffer.Length); - - if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 - Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes)); - - // Need to find AA FF and have - for (int i = 0; i < newBytes.Length; i++) - { - if (newBytes[i] == 0xAA && newBytes[i + 1] == 0xFF) - { - newBytes = newBytes.Skip(i).ToArray(); // Trim off junk if there's "dirt" in the buffer - - // parse it - // If it's at least got the header, then process it, - while (newBytes.Length > 4 && newBytes[0] == 0xAA && newBytes[1] == 0xFF) - { - var msgLen = newBytes[3]; - // if the buffer is shorter than the header (3) + message (msgLen) + checksum (1), - // give and save it for next time - if (newBytes.Length < msgLen + 4) - break; - - // Good length, grab the message - var message = newBytes.Skip(4).Take(msgLen).ToArray(); - - // At this point, the ack/nak is the first byte - if (message[0] == 0x41) - { - switch (message[1]) // type byte - { - case 0x00: // General status - //UpdatePowerFB(message[2], message[5]); // "power" can be misrepresented when the display sleeps - - // Handle the first power on fb when waiting for it. - if (IsPoweringOnIgnorePowerFb && message[2] == 0x01) - IsPoweringOnIgnorePowerFb = false; - // Ignore general-status power off messages when powering up - if (!(IsPoweringOnIgnorePowerFb && message[2] == 0x00)) - UpdatePowerFB(message[2]); - UpdateVolumeFB(message[3]); - UpdateMuteFb(message[4]); - UpdateInputFb(message[5]); - break; - - case 0x11: - UpdatePowerFB(message[2]); - break; - - case 0x12: - UpdateVolumeFB(message[2]); - break; - - case 0x13: - UpdateMuteFb(message[2]); - break; - - case 0x14: - UpdateInputFb(message[2]); - break; - - default: - break; - } - } - // Skip over what we've used and save the rest for next time - newBytes = newBytes.Skip(5 + msgLen).ToArray(); - } - - break; // parsing will mean we can stop looking for header in loop - } - } - - // Save whatever partial message is here - IncomingBuffer = newBytes; - } - catch (Exception err) - { - Debug.Console(2, this, "Error parsing feedback: {0}", err); - } - } - - /// - /// - /// - void UpdatePowerFB(byte powerByte) - { - var newVal = powerByte == 1; - if (newVal != _PowerIsOn) - { - _PowerIsOn = newVal; - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Feedback Power State: {0}", _PowerIsOn); - PowerIsOnFeedback.FireUpdate(); - } - } - - /// - /// Updates power status from general updates where source is included. - /// Compensates for errant standby / power off hiccups by ignoring - /// power off states with input < 0x10 - /// - void UpdatePowerFB(byte powerByte, byte inputByte) - { - // This should reject errant power feedbacks when switching away from input on standby. - if (powerByte == 0x01 && inputByte < 0x10) - IsInStandby = true; - if (powerByte == 0x00 && IsInStandby) // Ignore power off if coming from standby - glitch - { - IsInStandby = false; - return; - } - - UpdatePowerFB(powerByte); - } - - /// - /// - /// - void UpdateVolumeFB(byte b) - { - var newVol = (ushort)NumericalHelpers.Scale((double)b, 0, 100, 0, 65535); - if (!VolumeIsRamping) - _LastVolumeSent = newVol; - if (newVol != _VolumeLevelForSig) - { - _VolumeLevelForSig = newVol; - VolumeLevelFeedback.FireUpdate(); - } - } - - /// - /// - /// - void UpdateMuteFb(byte b) - { - var newMute = b == 1; - if (newMute != _IsMuted) - { - _IsMuted = newMute; - MuteFeedback.FireUpdate(); - } + + + public StatusMonitorBase CommunicationMonitor { get; private set; } + + public byte ID { get; private set; } + + bool LastCommandSentWasVolume; + + bool _PowerIsOn; + bool _IsWarmingUp; + bool _IsCoolingDown; + ushort _VolumeLevelForSig; + int _LastVolumeSent; + bool _IsMuted; + RoutingInputPort _CurrentInputPort; + byte[] IncomingBuffer = new byte[]{}; + ActionIncrementer VolumeIncrementer; + bool VolumeIsRamping; + public bool IsInStandby { get; private set; } + bool IsPoweringOnIgnorePowerFb; + + protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } + protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } + protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } + protected override Func CurrentInputFeedbackFunc { get { return () => _CurrentInputPort.Key; } } + + /// + /// Constructor for IBasicCommunication + /// + public SamsungMDC(string key, string name, IBasicCommunication comm, string id) + : base(key, name) + { + Communication = comm; + Communication.BytesReceived += new EventHandler(Communication_BytesReceived); + + ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor + Init(); + } + + /// + /// Constructor for TCP + /// + public SamsungMDC(string key, string name, string hostname, int port, string id) + : base(key, name) + { + Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000); + ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor + Init(); + } + + /// + /// Constructor for COM + /// + public SamsungMDC(string key, string name, ComPort port, ComPort.ComPortSpec spec, string id) + : base(key, name) + { + Communication = new ComPortController(key + "-com", port, spec); + //Communication.TextReceived += new EventHandler(Communication_TextReceived); + + ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor + Init(); + } + + void AddRoutingInputPort(RoutingInputPort port, byte fbMatch) + { + port.FeedbackMatchObject = fbMatch; + InputPorts.Add(port); } - - - - /// - /// - /// - void UpdateInputFb(byte b) - { - var newInput = InputPorts.FirstOrDefault(i => i.FeedbackMatchObject.Equals(b)); - if (newInput != null && newInput != _CurrentInputPort) - { - _CurrentInputPort = newInput; + void Init() + { + WarmupTime = 10000; + CooldownTime = 8000; + + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet); + DeviceManager.AddDevice(CommunicationMonitor); + + VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80, + v => SetVolume((ushort)v), + () => _LastVolumeSent); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this), 0x21); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1PC, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1PC), this), 0x22); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this), 0x23); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2PC, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2PC), this), 0x24); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this), 0x32); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this), 0x25); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this), 0x18); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Composite, new Action(InputVideo1), this), 0x08); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn1, eRoutingSignalType.Video, + eRoutingPortConnectionType.Vga, new Action(InputRgb1), this), 0x14); + + AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn2, eRoutingSignalType.Video, + eRoutingPortConnectionType.Rgb, new Action(new Action(InputRgb2)), this), 0x1E); + + VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevelForSig; }); + MuteFeedback = new BoolFeedback(() => _IsMuted); + + StatusGet(); + } + + /// + /// + /// + /// + public override bool CustomActivate() + { + Communication.Connect(); + CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); }; + CommunicationMonitor.Start(); + return true; + } + + public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); + } + + public override FeedbackCollection Feedbacks + { + get + { + var list = base.Feedbacks; + list.AddRange(new List + { + VolumeLevelFeedback, + MuteFeedback, + CurrentInputFeedback + }); + return list; + } + } + + /// + /// / + /// + /// + void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) + { + try + { + // This is probably not thread-safe buffering + // Append the incoming bytes with whatever is in the buffer + var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length]; + IncomingBuffer.CopyTo(newBytes, 0); + e.Bytes.CopyTo(newBytes, IncomingBuffer.Length); + + if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 + Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes)); + + // Need to find AA FF and have + for (int i = 0; i < newBytes.Length; i++) + { + if (newBytes[i] == 0xAA && newBytes[i + 1] == 0xFF) + { + newBytes = newBytes.Skip(i).ToArray(); // Trim off junk if there's "dirt" in the buffer + + // parse it + // If it's at least got the header, then process it, + while (newBytes.Length > 4 && newBytes[0] == 0xAA && newBytes[1] == 0xFF) + { + var msgLen = newBytes[3]; + // if the buffer is shorter than the header (3) + message (msgLen) + checksum (1), + // give and save it for next time + if (newBytes.Length < msgLen + 4) + break; + + // Good length, grab the message + var message = newBytes.Skip(4).Take(msgLen).ToArray(); + + // At this point, the ack/nak is the first byte + if (message[0] == 0x41) + { + switch (message[1]) // type byte + { + case 0x00: // General status + //UpdatePowerFB(message[2], message[5]); // "power" can be misrepresented when the display sleeps + + // Handle the first power on fb when waiting for it. + if (IsPoweringOnIgnorePowerFb && message[2] == 0x01) + IsPoweringOnIgnorePowerFb = false; + // Ignore general-status power off messages when powering up + if (!(IsPoweringOnIgnorePowerFb && message[2] == 0x00)) + UpdatePowerFB(message[2]); + UpdateVolumeFB(message[3]); + UpdateMuteFb(message[4]); + UpdateInputFb(message[5]); + break; + + case 0x11: + UpdatePowerFB(message[2]); + break; + + case 0x12: + UpdateVolumeFB(message[2]); + break; + + case 0x13: + UpdateMuteFb(message[2]); + break; + + case 0x14: + UpdateInputFb(message[2]); + break; + + default: + break; + } + } + // Skip over what we've used and save the rest for next time + newBytes = newBytes.Skip(5 + msgLen).ToArray(); + } + + break; // parsing will mean we can stop looking for header in loop + } + } + + // Save whatever partial message is here + IncomingBuffer = newBytes; + } + catch (Exception err) + { + Debug.Console(2, this, "Error parsing feedback: {0}", err); + } + } + + /// + /// + /// + void UpdatePowerFB(byte powerByte) + { + var newVal = powerByte == 1; + if (newVal != _PowerIsOn) + { + _PowerIsOn = newVal; + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Feedback Power State: {0}", _PowerIsOn); + PowerIsOnFeedback.FireUpdate(); + } + } + + /// + /// Updates power status from general updates where source is included. + /// Compensates for errant standby / power off hiccups by ignoring + /// power off states with input < 0x10 + /// + void UpdatePowerFB(byte powerByte, byte inputByte) + { + // This should reject errant power feedbacks when switching away from input on standby. + if (powerByte == 0x01 && inputByte < 0x10) + IsInStandby = true; + if (powerByte == 0x00 && IsInStandby) // Ignore power off if coming from standby - glitch + { + IsInStandby = false; + return; + } + + UpdatePowerFB(powerByte); + } + + /// + /// + /// + void UpdateVolumeFB(byte b) + { + var newVol = (ushort)NumericalHelpers.Scale((double)b, 0, 100, 0, 65535); + if (!VolumeIsRamping) + _LastVolumeSent = newVol; + if (newVol != _VolumeLevelForSig) + { + _VolumeLevelForSig = newVol; + VolumeLevelFeedback.FireUpdate(); + } + } + + /// + /// + /// + void UpdateMuteFb(byte b) + { + var newMute = b == 1; + if (newMute != _IsMuted) + { + _IsMuted = newMute; + MuteFeedback.FireUpdate(); + } + } + + + + + /// + /// + /// + void UpdateInputFb(byte b) + { + var newInput = InputPorts.FirstOrDefault(i => i.FeedbackMatchObject.Equals(b)); + if (newInput != null && newInput != _CurrentInputPort) + { + _CurrentInputPort = newInput; CurrentInputFeedback.FireUpdate(); - OnSwitchChange(new RoutingNumericEventArgs(null, _CurrentInputPort, eRoutingSignalType.AudioVideo)); - } - } - - /// - /// Formats an outgoing message. Replaces third byte with ID and replaces last byte with checksum - /// - /// - void SendBytes(byte[] b) - { - if (LastCommandSentWasVolume) // If the last command sent was volume - if (b[1] != 0x12) // Check if this command is volume, and if not, delay this command - CrestronEnvironment.Sleep(100); - - b[2] = ID; - // append checksum by adding all bytes, except last which should be 00 - int checksum = 0; - for (var i = 1; i < b.Length - 1; i++) // add 2nd through 2nd-to-last bytes - { - checksum += b[i]; - } - checksum = checksum & 0x000000FF; // mask off MSBs - b[b.Length - 1] = (byte)checksum; - if(Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 - Debug.Console(2, this, "Sending:{0}", ComTextHelper.GetEscapedText(b)); - - if (b[1] == 0x12) - LastCommandSentWasVolume = true; - else - LastCommandSentWasVolume = false; - - Communication.SendBytes(b); - } - - - /// - /// - /// - public void StatusGet() - { - SendBytes(new byte[] { 0xAA, 0x00, 0x00, 0x00, 0x00 }); - } - - /// - /// - /// - public override void PowerOn() - { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Powering On Display"); - - IsPoweringOnIgnorePowerFb = true; - //Send(PowerOnCmd); - SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x01, 0x00 }); - if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) - { - _IsWarmingUp = true; - IsWarmingUpFeedback.FireUpdate(); - // Fake power-up cycle - WarmupTimer = new CTimer(o => - { - _IsWarmingUp = false; - _PowerIsOn = true; - IsWarmingUpFeedback.FireUpdate(); - PowerIsOnFeedback.FireUpdate(); - }, WarmupTime); - } - } - - /// - /// - /// - public override void PowerOff() - { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Powering Off Display"); - - IsPoweringOnIgnorePowerFb = false; - // If a display has unreliable-power off feedback, just override this and - // remove this check. - if (!_IsWarmingUp && !_IsCoolingDown) // PowerIsOnFeedback.BoolValue && - { - //Send(PowerOffCmd); - SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x00, 0x00 }); - _IsCoolingDown = true; - _PowerIsOn = false; - PowerIsOnFeedback.FireUpdate(); - IsCoolingDownFeedback.FireUpdate(); - // Fake cool-down cycle - CooldownTimer = new CTimer(o => - { - _IsCoolingDown = false; - IsCoolingDownFeedback.FireUpdate(); - }, CooldownTime); - } - } - - public override void PowerToggle() - { - if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue) - PowerOff(); - else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue) - PowerOn(); - } - - public void PowerGet() - { - SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x00, 0x00 }); - } - - public void InputHdmi1() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x21, 0x00 }); - } - - public void InputHdmi1PC() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x22, 0x00 }); - } - - public void InputHdmi2() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x23, 0x00 }); - } - - public void InputHdmi2PC() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x24, 0x00 }); - } - - public void InputHdmi3() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x32, 0x00 }); - } - - public void InputHdmi4() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x34, 0x00 }); - } - - public void InputDisplayPort1() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x25, 0x00 }); - } - - public void InputDisplayPort2() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x26, 0x00 }); - } - - public void InputDvi1() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x18, 0x00 }); - } - - public void InputVideo1() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x08, 0x00 }); - } - - public void InputRgb1() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x14, 0x00 }); - } - - public void InputRgb2() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x1E, 0x00 }); - } - - public void InputGet() - { - SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x00, 0x00 }); - } - - - /// - /// Executes a switch, turning on display if necessary. - /// - /// - public override void ExecuteSwitch(object selector) - { - //if (!(selector is Action)) - // Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType()); - - if (_PowerIsOn) - (selector as Action)(); - else // if power is off, wait until we get on FB to send it. - { - // One-time event handler to wait for power on before executing switch - EventHandler handler = null; // necessary to allow reference inside lambda to handler - handler = (o, a) => - { - if (!_IsWarmingUp) // Done warming - { - IsWarmingUpFeedback.OutputChange -= handler; - (selector as Action)(); - } - }; - IsWarmingUpFeedback.OutputChange += handler; // attach and wait for on FB - PowerOn(); - } - } - - /// - /// Scales the level to the range of the display and sends the command - /// - /// - public void SetVolume(ushort level) - { - _LastVolumeSent = level; - var scaled = (int)NumericalHelpers.Scale(level, 0, 65535, 0, 100); - // The inputs to Scale ensure that byte won't overflow - SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x01, Convert.ToByte(scaled), 0x00 }); - } - - #region IBasicVolumeWithFeedback Members - - public IntFeedback VolumeLevelFeedback { get; private set; } - - public BoolFeedback MuteFeedback { get; private set; } - - /// - /// - /// - public void MuteOff() - { - SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x00, 0x00 }); - } - - /// - /// - /// - public void MuteOn() - { - SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x01, 0x00 }); - } - - /// - /// - /// - public void MuteGet() - { - SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x00, 0x00 }); - } - - #endregion - - #region IBasicVolumeControls Members - - /// - /// - /// - public void MuteToggle() - { - if (_IsMuted) - MuteOff(); - else - MuteOn(); - } - - /// - /// - /// - /// - public void VolumeDown(bool pressRelease) - { - if (pressRelease) - { - VolumeIncrementer.StartDown(); - VolumeIsRamping = true; - } - else - { - VolumeIsRamping = false; - VolumeIncrementer.Stop(); - } - } - - /// - /// - /// - /// - public void VolumeUp(bool pressRelease) - { - if (pressRelease) - { - VolumeIncrementer.StartUp(); - VolumeIsRamping = true; - } - else - { - VolumeIsRamping = false; - VolumeIncrementer.Stop(); - } - } - - /// - /// - /// - public void VolumeGet() - { - SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x00, 0x00 }); - } - - #endregion - } - - public class SamsungMDCFactory : EssentialsDeviceFactory - { - public SamsungMDCFactory() - { - TypeNames = new List() { "samsungmdc" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new Generic Comm Device"); - var comm = CommFactory.CreateCommForDevice(dc); - if (comm != null) - return new SamsungMDC(dc.Key, dc.Name, comm, dc.Properties["id"].Value()); - else - return null; - } - } - + OnSwitchChange(new RoutingNumericEventArgs(null, _CurrentInputPort, eRoutingSignalType.AudioVideo)); + } + } + + /// + /// Formats an outgoing message. Replaces third byte with ID and replaces last byte with checksum + /// + /// + void SendBytes(byte[] b) + { + if (LastCommandSentWasVolume) // If the last command sent was volume + if (b[1] != 0x12) // Check if this command is volume, and if not, delay this command + CrestronEnvironment.Sleep(100); + + b[2] = ID; + // append checksum by adding all bytes, except last which should be 00 + int checksum = 0; + for (var i = 1; i < b.Length - 1; i++) // add 2nd through 2nd-to-last bytes + { + checksum += b[i]; + } + checksum = checksum & 0x000000FF; // mask off MSBs + b[b.Length - 1] = (byte)checksum; + if(Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 + Debug.Console(2, this, "Sending:{0}", ComTextHelper.GetEscapedText(b)); + + if (b[1] == 0x12) + LastCommandSentWasVolume = true; + else + LastCommandSentWasVolume = false; + + Communication.SendBytes(b); + } + + + /// + /// + /// + public void StatusGet() + { + SendBytes(new byte[] { 0xAA, 0x00, 0x00, 0x00, 0x00 }); + } + + /// + /// + /// + public override void PowerOn() + { + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Powering On Display"); + + IsPoweringOnIgnorePowerFb = true; + //Send(PowerOnCmd); + SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x01, 0x00 }); + if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) + { + _IsWarmingUp = true; + IsWarmingUpFeedback.FireUpdate(); + // Fake power-up cycle + WarmupTimer = new CTimer(o => + { + _IsWarmingUp = false; + _PowerIsOn = true; + IsWarmingUpFeedback.FireUpdate(); + PowerIsOnFeedback.FireUpdate(); + }, WarmupTime); + } + } + + /// + /// + /// + public override void PowerOff() + { + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Powering Off Display"); + + IsPoweringOnIgnorePowerFb = false; + // If a display has unreliable-power off feedback, just override this and + // remove this check. + if (!_IsWarmingUp && !_IsCoolingDown) // PowerIsOnFeedback.BoolValue && + { + //Send(PowerOffCmd); + SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x00, 0x00 }); + _IsCoolingDown = true; + _PowerIsOn = false; + PowerIsOnFeedback.FireUpdate(); + IsCoolingDownFeedback.FireUpdate(); + // Fake cool-down cycle + CooldownTimer = new CTimer(o => + { + _IsCoolingDown = false; + IsCoolingDownFeedback.FireUpdate(); + }, CooldownTime); + } + } + + public override void PowerToggle() + { + if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue) + PowerOff(); + else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue) + PowerOn(); + } + + public void PowerGet() + { + SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x00, 0x00 }); + } + + public void InputHdmi1() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x21, 0x00 }); + } + + public void InputHdmi1PC() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x22, 0x00 }); + } + + public void InputHdmi2() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x23, 0x00 }); + } + + public void InputHdmi2PC() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x24, 0x00 }); + } + + public void InputHdmi3() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x32, 0x00 }); + } + + public void InputHdmi4() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x34, 0x00 }); + } + + public void InputDisplayPort1() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x25, 0x00 }); + } + + public void InputDisplayPort2() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x26, 0x00 }); + } + + public void InputDvi1() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x18, 0x00 }); + } + + public void InputVideo1() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x08, 0x00 }); + } + + public void InputRgb1() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x14, 0x00 }); + } + + public void InputRgb2() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x1E, 0x00 }); + } + + public void InputGet() + { + SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x00, 0x00 }); + } + + + /// + /// Executes a switch, turning on display if necessary. + /// + /// + public override void ExecuteSwitch(object selector) + { + //if (!(selector is Action)) + // Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType()); + + if (_PowerIsOn) + (selector as Action)(); + else // if power is off, wait until we get on FB to send it. + { + // One-time event handler to wait for power on before executing switch + EventHandler handler = null; // necessary to allow reference inside lambda to handler + handler = (o, a) => + { + if (!_IsWarmingUp) // Done warming + { + IsWarmingUpFeedback.OutputChange -= handler; + (selector as Action)(); + } + }; + IsWarmingUpFeedback.OutputChange += handler; // attach and wait for on FB + PowerOn(); + } + } + + /// + /// Scales the level to the range of the display and sends the command + /// + /// + public void SetVolume(ushort level) + { + _LastVolumeSent = level; + var scaled = (int)NumericalHelpers.Scale(level, 0, 65535, 0, 100); + // The inputs to Scale ensure that byte won't overflow + SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x01, Convert.ToByte(scaled), 0x00 }); + } + + #region IBasicVolumeWithFeedback Members + + public IntFeedback VolumeLevelFeedback { get; private set; } + + public BoolFeedback MuteFeedback { get; private set; } + + /// + /// + /// + public void MuteOff() + { + SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x00, 0x00 }); + } + + /// + /// + /// + public void MuteOn() + { + SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x01, 0x00 }); + } + + /// + /// + /// + public void MuteGet() + { + SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x00, 0x00 }); + } + + #endregion + + #region IBasicVolumeControls Members + + /// + /// + /// + public void MuteToggle() + { + if (_IsMuted) + MuteOff(); + else + MuteOn(); + } + + /// + /// + /// + /// + public void VolumeDown(bool pressRelease) + { + if (pressRelease) + { + VolumeIncrementer.StartDown(); + VolumeIsRamping = true; + } + else + { + VolumeIsRamping = false; + VolumeIncrementer.Stop(); + } + } + + /// + /// + /// + /// + public void VolumeUp(bool pressRelease) + { + if (pressRelease) + { + VolumeIncrementer.StartUp(); + VolumeIsRamping = true; + } + else + { + VolumeIsRamping = false; + VolumeIncrementer.Stop(); + } + } + + /// + /// + /// + public void VolumeGet() + { + SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x00, 0x00 }); + } + + #endregion + } + + public class SamsungMDCFactory : EssentialsDeviceFactory + { + public SamsungMDCFactory() + { + TypeNames = new List() { "samsungmdc" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new Generic Comm Device"); + var comm = CommFactory.CreateCommForDevice(dc); + if (comm != null) + return new SamsungMDC(dc.Key, dc.Name, comm, dc.Properties["id"].Value()); + else + return null; + } + } + } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/IRSetTopBoxBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/IRSetTopBoxBase.cs index 71698529..580d44cc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/IRSetTopBoxBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/IRSetTopBoxBase.cs @@ -56,6 +56,7 @@ namespace PepperDash.Essentials.Devices.Common eRoutingPortConnectionType.DigitalAudio, null, this); OutputPorts = new RoutingPortCollection { AnyVideoOut, AnyAudioOut }; + PowerIsOnFeedback = new BoolFeedback(() => false); } public void LoadPresets(string filePath) @@ -348,27 +349,21 @@ namespace PepperDash.Essentials.Devices.Common public void PowerOn() { - IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_ON, true); - IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_ON, false); - + IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, 200); } public void PowerOff() { - IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_OFF, true); - IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_OFF, false); - + IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, 200); } public void PowerToggle() { - throw new NotImplementedException(); + // TODO: Implement power toggle command pulse + IrPort.Pulse(IROutputStandardCommands.IROut_POWER, 200); } - public BoolFeedback PowerIsOnFeedback - { - get { throw new NotImplementedException(); } - } + public BoolFeedback PowerIsOnFeedback { get; private set; } #endregion @@ -395,79 +390,98 @@ namespace PepperDash.Essentials.Devices.Common trilist.StringInput[joinMap.Name.JoinNumber].StringValue = Name; var stbBase = this as ISetTopBoxControls; + if (stbBase != null) + { + trilist.BooleanInput[joinMap.HasDpad.JoinNumber].BoolValue = stbBase.HasDpad; + trilist.BooleanInput[joinMap.HasNumeric.JoinNumber].BoolValue = stbBase.HasNumeric; + trilist.BooleanInput[joinMap.HasDvr.JoinNumber].BoolValue = stbBase.HasDvr; + trilist.BooleanInput[joinMap.HasPresets.JoinNumber].BoolValue = stbBase.HasPresets; - trilist.BooleanInput[joinMap.HasDpad.JoinNumber].BoolValue = stbBase.HasDpad; - trilist.BooleanInput[joinMap.HasNumeric.JoinNumber].BoolValue = stbBase.HasNumeric; - trilist.BooleanInput[joinMap.HasDvr.JoinNumber].BoolValue = stbBase.HasDvr; - trilist.BooleanInput[joinMap.HasPresets.JoinNumber].BoolValue = stbBase.HasPresets; + trilist.SetBoolSigAction(joinMap.DvrList.JoinNumber, stbBase.DvrList); + trilist.SetBoolSigAction(joinMap.Replay.JoinNumber, stbBase.Replay); - trilist.SetBoolSigAction(joinMap.DvrList.JoinNumber, stbBase.DvrList); - trilist.SetBoolSigAction(joinMap.Replay.JoinNumber, stbBase.Replay); - - trilist.SetStringSigAction(joinMap.LoadPresets.JoinNumber, stbBase.LoadPresets); + trilist.SetStringSigAction(joinMap.LoadPresets.JoinNumber, stbBase.LoadPresets); + } var stbPower = this as IPower; - - trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, stbPower.PowerOn); - trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, stbPower.PowerOff); - trilist.SetSigTrueAction(joinMap.PowerToggle.JoinNumber, stbPower.PowerToggle); + if (stbPower != null) + { + trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, stbPower.PowerOn); + trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, stbPower.PowerOff); + trilist.SetSigTrueAction(joinMap.PowerToggle.JoinNumber, stbPower.PowerToggle); + } var stbDPad = this as IDPad; - trilist.SetBoolSigAction(joinMap.Up.JoinNumber, stbDPad.Up); - trilist.SetBoolSigAction(joinMap.Down.JoinNumber, stbDPad.Down); - trilist.SetBoolSigAction(joinMap.Left.JoinNumber, stbDPad.Left); - trilist.SetBoolSigAction(joinMap.Right.JoinNumber, stbDPad.Right); - trilist.SetBoolSigAction(joinMap.Select.JoinNumber, stbDPad.Select); - trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, stbDPad.Menu); - trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbDPad.Exit); + if (stbDPad != null) + { + trilist.SetBoolSigAction(joinMap.Up.JoinNumber, stbDPad.Up); + trilist.SetBoolSigAction(joinMap.Down.JoinNumber, stbDPad.Down); + trilist.SetBoolSigAction(joinMap.Left.JoinNumber, stbDPad.Left); + trilist.SetBoolSigAction(joinMap.Right.JoinNumber, stbDPad.Right); + trilist.SetBoolSigAction(joinMap.Select.JoinNumber, stbDPad.Select); + trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, stbDPad.Menu); + trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbDPad.Exit); + } var stbChannel = this as IChannel; - trilist.SetBoolSigAction(joinMap.ChannelUp.JoinNumber, stbChannel.ChannelUp); - trilist.SetBoolSigAction(joinMap.ChannelDown.JoinNumber, stbChannel.ChannelDown); - trilist.SetBoolSigAction(joinMap.LastChannel.JoinNumber, stbChannel.LastChannel); - trilist.SetBoolSigAction(joinMap.Guide.JoinNumber, stbChannel.Guide); - trilist.SetBoolSigAction(joinMap.Info.JoinNumber, stbChannel.Info); - trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbChannel.Exit); + if (stbChannel != null) + { + trilist.SetBoolSigAction(joinMap.ChannelUp.JoinNumber, stbChannel.ChannelUp); + trilist.SetBoolSigAction(joinMap.ChannelDown.JoinNumber, stbChannel.ChannelDown); + trilist.SetBoolSigAction(joinMap.LastChannel.JoinNumber, stbChannel.LastChannel); + trilist.SetBoolSigAction(joinMap.Guide.JoinNumber, stbChannel.Guide); + trilist.SetBoolSigAction(joinMap.Info.JoinNumber, stbChannel.Info); + trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbChannel.Exit); + } var stbColor = this as IColor; - trilist.SetBoolSigAction(joinMap.Red.JoinNumber, stbColor.Red); - trilist.SetBoolSigAction(joinMap.Green.JoinNumber, stbColor.Green); - trilist.SetBoolSigAction(joinMap.Yellow.JoinNumber, stbColor.Yellow); - trilist.SetBoolSigAction(joinMap.Blue.JoinNumber, stbColor.Blue); + if (stbColor != null) + { + trilist.SetBoolSigAction(joinMap.Red.JoinNumber, stbColor.Red); + trilist.SetBoolSigAction(joinMap.Green.JoinNumber, stbColor.Green); + trilist.SetBoolSigAction(joinMap.Yellow.JoinNumber, stbColor.Yellow); + trilist.SetBoolSigAction(joinMap.Blue.JoinNumber, stbColor.Blue); + } var stbKeypad = this as ISetTopBoxNumericKeypad; - trilist.StringInput[joinMap.KeypadAccessoryButton1Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton1Label; - trilist.StringInput[joinMap.KeypadAccessoryButton2Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton2Label; + if (stbKeypad != null) + { + trilist.StringInput[joinMap.KeypadAccessoryButton1Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton1Label; + trilist.StringInput[joinMap.KeypadAccessoryButton2Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton2Label; - trilist.BooleanInput[joinMap.HasKeypadAccessoryButton1.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton1; - trilist.BooleanInput[joinMap.HasKeypadAccessoryButton2.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton2; + trilist.BooleanInput[joinMap.HasKeypadAccessoryButton1.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton1; + trilist.BooleanInput[joinMap.HasKeypadAccessoryButton2.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton2; - trilist.SetBoolSigAction(joinMap.Digit0.JoinNumber, stbKeypad.Digit0); - trilist.SetBoolSigAction(joinMap.Digit1.JoinNumber, stbKeypad.Digit1); - trilist.SetBoolSigAction(joinMap.Digit2.JoinNumber, stbKeypad.Digit2); - trilist.SetBoolSigAction(joinMap.Digit3.JoinNumber, stbKeypad.Digit3); - trilist.SetBoolSigAction(joinMap.Digit4.JoinNumber, stbKeypad.Digit4); - trilist.SetBoolSigAction(joinMap.Digit5.JoinNumber, stbKeypad.Digit5); - trilist.SetBoolSigAction(joinMap.Digit6.JoinNumber, stbKeypad.Digit6); - trilist.SetBoolSigAction(joinMap.Digit7.JoinNumber, stbKeypad.Digit7); - trilist.SetBoolSigAction(joinMap.Digit8.JoinNumber, stbKeypad.Digit8); - trilist.SetBoolSigAction(joinMap.Digit9.JoinNumber, stbKeypad.Digit9); - trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton1Press.JoinNumber, stbKeypad.KeypadAccessoryButton1); - trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton2Press.JoinNumber, stbKeypad.KeypadAccessoryButton1); - trilist.SetBoolSigAction(joinMap.Dash.JoinNumber, stbKeypad.Dash); - trilist.SetBoolSigAction(joinMap.KeypadEnter.JoinNumber, stbKeypad.KeypadEnter); + trilist.SetBoolSigAction(joinMap.Digit0.JoinNumber, stbKeypad.Digit0); + trilist.SetBoolSigAction(joinMap.Digit1.JoinNumber, stbKeypad.Digit1); + trilist.SetBoolSigAction(joinMap.Digit2.JoinNumber, stbKeypad.Digit2); + trilist.SetBoolSigAction(joinMap.Digit3.JoinNumber, stbKeypad.Digit3); + trilist.SetBoolSigAction(joinMap.Digit4.JoinNumber, stbKeypad.Digit4); + trilist.SetBoolSigAction(joinMap.Digit5.JoinNumber, stbKeypad.Digit5); + trilist.SetBoolSigAction(joinMap.Digit6.JoinNumber, stbKeypad.Digit6); + trilist.SetBoolSigAction(joinMap.Digit7.JoinNumber, stbKeypad.Digit7); + trilist.SetBoolSigAction(joinMap.Digit8.JoinNumber, stbKeypad.Digit8); + trilist.SetBoolSigAction(joinMap.Digit9.JoinNumber, stbKeypad.Digit9); + trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton1Press.JoinNumber, stbKeypad.KeypadAccessoryButton1); + trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton2Press.JoinNumber, stbKeypad.KeypadAccessoryButton1); + trilist.SetBoolSigAction(joinMap.Dash.JoinNumber, stbKeypad.Dash); + trilist.SetBoolSigAction(joinMap.KeypadEnter.JoinNumber, stbKeypad.KeypadEnter); + } var stbTransport = this as ITransport; - trilist.SetBoolSigAction(joinMap.Play.JoinNumber, stbTransport.Play); - trilist.SetBoolSigAction(joinMap.Pause.JoinNumber, stbTransport.Pause); - trilist.SetBoolSigAction(joinMap.Rewind.JoinNumber, stbTransport.Rewind); - trilist.SetBoolSigAction(joinMap.FFwd.JoinNumber, stbTransport.FFwd); - trilist.SetBoolSigAction(joinMap.ChapMinus.JoinNumber, stbTransport.ChapMinus); - trilist.SetBoolSigAction(joinMap.ChapPlus.JoinNumber, stbTransport.ChapPlus); - trilist.SetBoolSigAction(joinMap.Stop.JoinNumber, stbTransport.Stop); - trilist.SetBoolSigAction(joinMap.Record.JoinNumber, stbTransport.Record); + if (stbTransport != null) + { + trilist.SetBoolSigAction(joinMap.Play.JoinNumber, stbTransport.Play); + trilist.SetBoolSigAction(joinMap.Pause.JoinNumber, stbTransport.Pause); + trilist.SetBoolSigAction(joinMap.Rewind.JoinNumber, stbTransport.Rewind); + trilist.SetBoolSigAction(joinMap.FFwd.JoinNumber, stbTransport.FFwd); + trilist.SetBoolSigAction(joinMap.ChapMinus.JoinNumber, stbTransport.ChapMinus); + trilist.SetBoolSigAction(joinMap.ChapPlus.JoinNumber, stbTransport.ChapPlus); + trilist.SetBoolSigAction(joinMap.Stop.JoinNumber, stbTransport.Stop); + trilist.SetBoolSigAction(joinMap.Record.JoinNumber, stbTransport.Record); + } } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 55e6bf11..ce748699 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1970,6 +1970,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } + /// + /// Sets the selected source of the available external sources on teh Touch10 UI + /// + public void SetSelectedSource(string key) + { + SendText(string.Format("xCommand UserInterface Presentation ExternalSource Select SourceIdentifier: {0}", key)); + } + /// /// Action that will run when the External Source is selected. ///