From ed5bd360b476695d85b5c203decedb1735f15eb2 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 14 Mar 2024 10:46:48 -0600 Subject: [PATCH 1/5] feat: adds more generic ISelectableItems and ISelectableItem interfaces and implements on new IHasInputs and IHasSurroundSoundModes --- .../DeviceTypeInterfaces/IHasInputs.cs | 12 +++++++--- .../IHasSurroundSoundModes.cs | 17 ++++++++++++++ .../DeviceTypeInterfaces/IInput.cs | 12 ---------- .../DeviceTypeInterfaces/ISelectableItem.cs | 19 ++++++++++++++++ .../DeviceTypeInterfaces/ISelectableItems.cs | 22 +++++++++++++++++++ 5 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs delete mode 100644 src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IInput.cs create mode 100644 src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs create mode 100644 src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs index b0d14e9c..a9f59c35 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs @@ -1,11 +1,17 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; namespace PepperDash.Essentials.Core.DeviceTypeInterfaces { + + /// + /// Describes a device that has selectable inputs + /// public interface IHasInputs { - event EventHandler InputsUpdated; - IDictionary Inputs { get; } + ISelectableItems Inputs { get; } } -} \ No newline at end of file +} diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs new file mode 100644 index 00000000..83e48105 --- /dev/null +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + /// + /// Describes a device that has selectable surround sound modes + /// + /// the type to use as the key for each input item. Most likely an enum or string + public interface IHasSurroundSoundModes + { + ISelectableItems SurroundSoundModes { get; } + } +} diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IInput.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IInput.cs deleted file mode 100644 index fc49e390..00000000 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IInput.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using PepperDash.Core; - -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces -{ - public interface IInput : IKeyName - { - event EventHandler InputUpdated; - bool IsSelected { get; } - void Select(); - } -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs new file mode 100644 index 00000000..525581d3 --- /dev/null +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs @@ -0,0 +1,19 @@ +using System; +using Newtonsoft.Json; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + + /// + /// Describes an item that can be selected + /// + public interface ISelectableItem : IKeyName + { + event EventHandler ItemUpdated; + + [JsonProperty("isSelected")] + bool IsSelected { get; } + void Select(); + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs new file mode 100644 index 00000000..ba936963 --- /dev/null +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; + +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +{ + /// + /// Describes a collection of items that can be selected + /// + /// type for the keys in the collection. Probably a string or enum + public interface ISelectableItems + { + event EventHandler ItemsUpdated; + event EventHandler CurrentItemChanged; + + + Dictionary Items { get; } + + [JsonProperty("currentItem")] + string CurrentItem { get; } + } +} \ No newline at end of file From a2e4c2fad6d5bc492d0b2310737b566c689296a8 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 14 Mar 2024 11:55:46 -0600 Subject: [PATCH 2/5] feat: Adds ISelectableItems/Item and IHasSurroundSoundModes, modfies IHasInputs, Updates MockDisplay to implement IHasInputs --- .../DeviceTypeInterfaces/IHasInputs.cs | 13 ++- .../IHasSurroundSoundModes.cs | 5 +- .../DeviceTypeInterfaces/ISelectableItem.cs | 2 +- .../DeviceTypeInterfaces/ISelectableItems.cs | 4 +- .../Displays/DisplayBase.cs | 8 +- .../Displays/MockDisplay.cs | 95 +++++++++++++----- .../Displays/MockDisplayInputs.cs | 97 +++++++++++++++++++ 7 files changed, 190 insertions(+), 34 deletions(-) create mode 100644 src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs index a9f59c35..ef806d9a 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs @@ -1,4 +1,5 @@ -using System; +using PepperDash.Core; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -10,8 +11,14 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// /// Describes a device that has selectable inputs /// - public interface IHasInputs + /// the type to use as the key for each input item. Most likely an enum or string\ + /// + /// See MockDisplay for example implemntation + /// + public interface IHasInputs: IKeyName { - ISelectableItems Inputs { get; } + ISelectableItems Inputs { get; } + + void SetInput(TSelector selector); } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs index 83e48105..85b01319 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs @@ -1,4 +1,5 @@ -using System; +using PepperDash.Core; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -10,7 +11,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// Describes a device that has selectable surround sound modes /// /// the type to use as the key for each input item. Most likely an enum or string - public interface IHasSurroundSoundModes + public interface IHasSurroundSoundModes: IKeyName { ISelectableItems SurroundSoundModes { get; } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs index 525581d3..0f7408f6 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs @@ -13,7 +13,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces event EventHandler ItemUpdated; [JsonProperty("isSelected")] - bool IsSelected { get; } + bool IsSelected { get; set; } void Select(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs index ba936963..7d64ff10 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs @@ -14,9 +14,9 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces event EventHandler CurrentItemChanged; - Dictionary Items { get; } + Dictionary Items { get; set; } [JsonProperty("currentItem")] - string CurrentItem { get; } + string CurrentItem { get; set; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs b/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs index 76e04405..17edfad0 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs @@ -8,10 +8,16 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using Feedback = PepperDash.Essentials.Core.Feedback; using Newtonsoft.Json; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; namespace PepperDash.Essentials.Devices.Common.Displays { - public abstract class DisplayBase : EssentialsDevice, IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking + public abstract class DisplayBase : EssentialsDevice + , IHasFeedback + , IRoutingSinkWithSwitching + , IHasPowerControl + , IWarmingCooling + , IUsageTracking { public event SourceInfoChangeHandler CurrentSourceChange; diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs index ffbb00cd..a183b1d6 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs @@ -1,21 +1,19 @@ using System; +using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharp; using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.Routing; namespace PepperDash.Essentials.Devices.Common.Displays { - public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced - + public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs { - public RoutingInputPort HdmiIn1 { get; private set; } - public RoutingInputPort HdmiIn2 { get; private set; } - public RoutingInputPort HdmiIn3 { get; private set; } - public RoutingInputPort ComponentIn1 { get; private set; } - public RoutingInputPort VgaIn1 { get; private set; } + public ISelectableItems Inputs { get; private set; } bool _PowerIsOn; bool _IsWarmingUp; @@ -53,7 +51,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays }; } } - protected override Func CurrentInputFeedbackFunc { get { return () => "Not Implemented"; } } + protected override Func CurrentInputFeedbackFunc { get { return () => Inputs.CurrentItem; } } int VolumeHeldRepeatInterval = 200; ushort VolumeInterval = 655; @@ -63,17 +61,31 @@ namespace PepperDash.Essentials.Devices.Common.Displays public MockDisplay(string key, string name) : base(key, name) { - HdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - HdmiIn3 = new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - ComponentIn1 = new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Video, - eRoutingPortConnectionType.Component, null, this); - VgaIn1 = new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.Video, - eRoutingPortConnectionType.Composite, null, this); - InputPorts.AddRange(new[] { HdmiIn1, HdmiIn2, HdmiIn3, ComponentIn1, VgaIn1 }); + Inputs = new MockDisplayInputs + { + Items = new Dictionary + { + { "HDMI1", new MockDisplayInput ( "HDMI1", "HDMI 1",this ) }, + { "HDMI2", new MockDisplayInput ("HDMI2", "HDMI 2",this ) }, + { "HDMI3", new MockDisplayInput ("HDMI3", "HDMI 3",this ) }, + { "HDMI4", new MockDisplayInput ("HDMI4", "HDMI 4",this )}, + { "DP", new MockDisplayInput ("DP", "DisplayPort", this ) } + } + }; + + Inputs.CurrentItemChanged += (o, a) => CurrentInputFeedback.FireUpdate(); + + var hdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, "HDMI1", this); + var hdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, "HDMI2", this); + var hdmiIn3 = new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, "HDMI3", this); + var hdmiIn4 = new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, "HDMI4", this); + var dpIn = new RoutingInputPort(RoutingPortNames.DisplayPortIn, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.DisplayPort, "DP", this); + InputPorts.AddRange(new[] { hdmiIn1, hdmiIn2, hdmiIn3, hdmiIn4, dpIn }); VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; }); MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted); @@ -135,13 +147,43 @@ namespace PepperDash.Essentials.Devices.Common.Displays { PowerOn(); } + + if (!Inputs.Items.TryGetValue(selector.ToString(), out var input)) + return; + + input.Select(); } + public void SetInput(string selector) + { + ISelectableItem currentInput = null; + + try + { + currentInput = Inputs.Items.SingleOrDefault(Inputs => Inputs.Value.IsSelected).Value; + } + catch { } + + + if (currentInput != null) + { + Debug.Console(2, this, "SetInput: {0}", selector); + currentInput.IsSelected = false; + } + + if (!Inputs.Items.TryGetValue(selector, out var input)) + return; + + input.IsSelected = true; + + Inputs.CurrentItem = selector; + } - #region IBasicVolumeWithFeedback Members - public IntFeedback VolumeLevelFeedback { get; private set; } + #region IBasicVolumeWithFeedback Members + + public IntFeedback VolumeLevelFeedback { get; private set; } public void SetVolume(ushort level) { @@ -163,11 +205,12 @@ namespace PepperDash.Essentials.Devices.Common.Displays public BoolFeedback MuteFeedback { get; private set; } - #endregion - #region IBasicVolumeControls Members + #endregion - public void VolumeUp(bool pressRelease) + #region IBasicVolumeControls Members + + public void VolumeUp(bool pressRelease) { //while (pressRelease) //{ @@ -207,5 +250,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays { LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); } - } + + + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs new file mode 100644 index 00000000..9035508a --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs @@ -0,0 +1,97 @@ +using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Devices.Common.Displays +{ + public class MockDisplayInputs : ISelectableItems + { + private Dictionary _inputs; + + public Dictionary Items + { + get + { + return _inputs; + } + set + { + if (_inputs == value) + return; + + _inputs = value; + + ItemsUpdated?.Invoke(this, null); + } + } + + private string _currentItem; + + public string CurrentItem + { + get + { + return _currentItem; + } + set + { + if (_currentItem == value) + return; + + _currentItem = value; + + CurrentItemChanged?.Invoke(this, null); + } + } + + public event EventHandler ItemsUpdated; + public event EventHandler CurrentItemChanged; + } + + public class MockDisplayInput : ISelectableItem + { + private IHasInputs _parent; + + + private bool _isSelected; + + public bool IsSelected + { + get + { + return _isSelected; + } + set + { + if (_isSelected == value) + return; + + _isSelected = value; + + ItemUpdated?.Invoke(this, null); + } + } + + public string Name { get; set; } + + public string Key { get; set; } + + public event EventHandler ItemUpdated; + + public MockDisplayInput(string key, string name, MockDisplay parent) + { + Key = key; + Name = name; + _parent = parent; + } + + public void Select() + { + _parent.SetInput(Key); + } + } +} From 0f57799382a6658b1a942696424f56c34b695581 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 14 Mar 2024 12:26:05 -0600 Subject: [PATCH 3/5] feat: Adds TSelector generic type to IHasSurroundSoundModes --- .../DeviceTypeInterfaces/IHasSurroundSoundModes.cs | 4 +++- .../Displays/MockDisplayInputs.cs | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs index 85b01319..c1c4ec86 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs @@ -11,8 +11,10 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// Describes a device that has selectable surround sound modes /// /// the type to use as the key for each input item. Most likely an enum or string - public interface IHasSurroundSoundModes: IKeyName + public interface IHasSurroundSoundModes: IKeyName { ISelectableItems SurroundSoundModes { get; } + + void SetSurroundSoundMode(TSelector selector); } } diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs index 9035508a..f6fb7bc0 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs @@ -10,20 +10,20 @@ namespace PepperDash.Essentials.Devices.Common.Displays { public class MockDisplayInputs : ISelectableItems { - private Dictionary _inputs; + private Dictionary _items; public Dictionary Items { get { - return _inputs; + return _items; } set { - if (_inputs == value) + if (_items == value) return; - _inputs = value; + _items = value; ItemsUpdated?.Invoke(this, null); } From 8ae8a3ef41d21148792e892d5fed0c2166249c46 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 14 Mar 2024 16:13:02 -0600 Subject: [PATCH 4/5] fix: adds missing JsonProperty decorator --- .../DeviceTypeInterfaces/ISelectableItems.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs index 7d64ff10..c1451afb 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs @@ -13,7 +13,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces event EventHandler ItemsUpdated; event EventHandler CurrentItemChanged; - + [JsonProperty("items")] Dictionary Items { get; set; } [JsonProperty("currentItem")] From 62f182c63443c36dca3a17aff81ccc917269d3eb Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 14 Mar 2024 22:28:26 -0600 Subject: [PATCH 5/5] debug: removes annoying console statements at startup --- src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs index e79075a6..d3f3d8b3 100644 --- a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs +++ b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs @@ -371,9 +371,9 @@ namespace PepperDash.Essentials { try { - Debug.Console(0, $"Checking if type {type.Name} is IPluginDeviceFactory"); + //Debug.Console(0, $"Checking if type {type.Name} is IPluginDeviceFactory"); - Debug.Console(0, $"{type.Name} is plugin factory: {typeof(IPluginDeviceFactory).IsAssignableFrom(type) && !type.IsAbstract}"); + //Debug.Console(0, $"{type.Name} is plugin factory: {typeof(IPluginDeviceFactory).IsAssignableFrom(type) && !type.IsAbstract}"); if (typeof (IPluginDeviceFactory).IsAssignableFrom(type) && !type.IsAbstract) {