diff --git a/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo b/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo index 6a48bbc5..1bcc9dfe 100644 Binary files a/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo and b/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo differ diff --git a/Essentials DM/Essentials_DM/Essentials_DM.projectinfo b/Essentials DM/Essentials_DM/Essentials_DM.projectinfo index 024f38e7..ad2c3757 100644 Binary files a/Essentials DM/Essentials_DM/Essentials_DM.projectinfo and b/Essentials DM/Essentials_DM/Essentials_DM.projectinfo differ diff --git a/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs b/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs new file mode 100644 index 00000000..c3f4cad6 --- /dev/null +++ b/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs @@ -0,0 +1,487 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Routing; + +namespace PepperDash.Essentials.Devices.Displays +{ + /// + /// + /// + public class SamsungMDC : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor + { + public IBasicCommunication Communication { get; private set; } + public CommunicationGather PortGather { get; private set; } + public StatusMonitorBase CommunicationMonitor { get; private set; } + + #region Command constants + + public string Ack + { + get { return AssembleCommand(string.Format("\xAA\xFF{0}\x03A", ID)); } + } + public string Nak + { + get { return AssembleCommand(string.Format("\xAA\xFF{0}\x03N", ID)); } + } + + // Power Commands + + public string PowerGetCmd + { + get { return AssembleCommand(string.Format("\x11{0}\x00", ID)); } + } + + public string PowerOnCmd + { + get { return AssembleCommand(string.Format("\x11{0}\x01\x01", ID)); } + } + + public string PowerOffCmd + { + get { return AssembleCommand(string.Format("\x11{0}\x01\x00", ID)); } + } + + // Input Commands + + public string InputGetCmd + { + get { return AssembleCommand(string.Format("\x14{0}\x00", ID)); } + } + + public string Dp1Cmd + { + get { return AssembleCommand(string.Format("\x14{0}\x01\x25", ID)); } + } + + public string Hdmi1Cmd + { + get { return AssembleCommand(string.Format("\x14{0}\x01\x21", ID)); } + } + + public string Hdmi2Cmd + { + get { return AssembleCommand(string.Format("\x14{0}\x01\x23", ID)); } + } + + public string Hdmi3Cmd + { + get { return AssembleCommand(string.Format("\x14{0}\x01\x32", ID)); } + } + + public string Dvi1Cmd + { + get { return AssembleCommand(string.Format("\x14{0}\x01\x18", ID)); } + } + + public string Rgb1Cmd + { + get { return AssembleCommand(string.Format("\x14{0}\x01\x14", ID)); } + } + + public string Rgb2Cmd + { + get { return AssembleCommand(string.Format("\x14{0}\x01\x1E", ID)); } + } + + public string CompCmd + { + get { return AssembleCommand(string.Format("\x14{0}\x01\x08", ID)); } + } + + // Volume Commands + + public string MuteGetCmd + { + get { return AssembleCommand(string.Format("\x13{0}\x00", ID)); } + } + + public string MuteOnCmd + { + get { return AssembleCommand(string.Format("\x13{0}\x01\x01", ID)); } + } + + public string MuteOffCmd + { + get { return AssembleCommand(string.Format("\x13{0}\x01\x00", ID)); } + } + + public string VolumeGetCmd + { + get { return AssembleCommand(string.Format("\x12{0}\x00", ID)); } + } + + /// + /// To be appended with the requested volume level. Does not include checksum calculation + /// + public string VolumeLevelCmd + { + get { return string.Format("\x1s{0}\x01", ID); } + } + + + + + + //public string InputGetCmd = ""; + //public const string Hdmi1Cmd = ""; + //public const string Hdmi2Cmd = ""; + //public const string Hdmi3Cmd = ""; + //public const string Hdmi4Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x38\x33\x03\x79\x0D"; + //public const string Dp1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x46\x03\x04\x0D"; + //public const string Dp2Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x30\x03\x73\x0D"; + //public const string Dvi1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x33\x03\x71\x0d"; + //public const string Video1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x35\x03\x77\x0D"; + //public const string VgaCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x31\x03\x73\x0D"; + //public const string RgbCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x32\x03\x70\x0D"; + + //public const string PowerOnCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x31\x03\x73\x0D"; + //public const string PowerOffCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x34\x03\x76\x0D"; + //public const string PowerToggleIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x30\x33\x30\x33\x03\x02\x0D"; + + //public const string MuteOffCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x38\x44\x30\x30\x30\x30\x03\x08\x0D"; + //public const string MuteOnCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x38\x44\x30\x30\x30\x31\x03\x09\x0D"; + //public const string MuteToggleIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x42\x30\x33\x03\x72\x0D"; + //public const string MuteGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x38\x44\x03\x79\x0D"; + + //public const string VolumeGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x36\x32\x03\x01\x0D"; + //public const string VolumeLevelPartialCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x32"; //\x46\x46\x46\x46\x03\xNN\x0D + //public const string VolumeUpCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x31\x30\x41\x44\x30\x30\x30\x31\x03\x71\x0D"; + //public const string VolumeDownCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x31\x30\x41\x44\x30\x30\x30\x32\x03\x72\x0D"; + + //public const string MenuIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x30\x30\x33\x03\x03\x0D"; + //public const string UpIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x35\x30\x33\x03\x05\x0D"; + //public const string DownIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x34\x30\x33\x03\x04\x0D"; + //public const string LeftIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x31\x30\x33\x03\x02\x0D"; + //public const string RightIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x32\x30\x33\x03\x01\x0D"; + //public const string SelectIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x33\x30\x33\x03\x00\x0D"; + //public const string ExitIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x46\x30\x33\x03\x76\x0D"; + #endregion + + + public byte ID { get; private set; } + + /// + /// Builds the command by including the ID of the display and calculating the checksum + /// + /// + /// + private string AssembleCommand(string command) + { + double checksum = 0; + + var bytes = command.ToCharArray(); + + for (int i = 1; i < bytes.Length; i++) + { + checksum = checksum + Char.GetNumericValue(bytes[i]); + } + + string result = string.Format("{0}{1}", command, checksum); + + return result; + + } + + bool _PowerIsOn; + bool _IsWarmingUp; + bool _IsCoolingDown; + ushort _VolumeLevel; + bool _IsMuted; + + protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } + protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } + protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } + + /// + /// Constructor for IBasicCommunication + /// + public SamsungMDC(string key, string name, IBasicCommunication comm) + : base(key, name) + { + Communication = comm; + Init(); + } + /// + /// Constructor for TCP + /// + public SamsungMDC(string key, string name, string hostname, int port, byte id) + : base(key, name) + { + Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000); + Init(); + } + + + /// + /// Constructor for COM + /// + public SamsungMDC(string key, string name, ComPort port, ComPort.ComPortSpec spec, byte id) + : base(key, name) + { + Communication = new ComPortController(key + "-com", port, spec); + Init(); + } + + void Init() + { + PortGather = new CommunicationGather(Communication, '\x0d'); + PortGather.LineReceived += this.Port_LineReceived; + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, "xx\x0d"); + + InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this)); + InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this)); + InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this)); + InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, new Action(InputHdmi4), this)); + InputPorts.Add(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this)); + InputPorts.Add(new RoutingInputPort(RoutingPortNames.DisplayPortIn2, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort2), this)); + InputPorts.Add(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this)); + InputPorts.Add(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Composite, new Action(InputVideo1), this)); + InputPorts.Add(new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.Video, + eRoutingPortConnectionType.Vga, new Action(InputVga), this)); + InputPorts.Add(new RoutingInputPort(RoutingPortNames.RgbIn, eRoutingSignalType.Video, + eRoutingPortConnectionType.Rgb, new Action(new Action(InputRgb)), this)); + + VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevel; }); + MuteFeedback = new BoolFeedback(() => _IsMuted); + + // new BoolCueActionPair(CommonBoolCue.Menu, b => { if(b) Send(MenuIrCmd); }), + // new BoolCueActionPair(CommonBoolCue.Up, b => { if(b) Send(UpIrCmd); }), + // new BoolCueActionPair(CommonBoolCue.Down, b => { if(b) Send(DownIrCmd); }), + // new BoolCueActionPair(CommonBoolCue.Left, b => { if(b) Send(LeftIrCmd); }), + // new BoolCueActionPair(CommonBoolCue.Right, b => { if(b) Send(RightIrCmd); }), + // new BoolCueActionPair(CommonBoolCue.Select, b => { if(b) Send(SelectIrCmd); }), + // new BoolCueActionPair(CommonBoolCue.Exit, b => { if(b) Send(ExitIrCmd); }), + //}; + } + + ~SamsungMDC() + { + PortGather = null; + } + + 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 override List Feedbacks + { + get + { + var list = base.Feedbacks; + list.AddRange(new List + { + + }); + return list; + } + } + + void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) + { + if (Debug.Level == 2) + Debug.Console(2, this, "Received: '{0}'", ComTextHelper.GetEscapedText(args.Text)); + + if (args.Text=="DO SOMETHING HERE EVENTUALLY") + { + _IsMuted = true; + MuteFeedback.FireUpdate(); + } + } + + //void AppendChecksumAndSend(string s) + //{ + // int x = 0; + // for (int i = 1; i < s.Length; i++) + // x = x ^ s[i]; + + // string send = s + (char)x + '\x0d'; + // Send(send); + //} + + void Send(string s) + { + if (Debug.Level == 2) + Debug.Console(2, this, "Send: '{0}'", ComTextHelper.GetEscapedText(s)); + Communication.SendText(s); + } + + + public override void PowerOn() + { + Send(PowerOnCmd); + 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() + { + // If a display has unreliable-power off feedback, just override this and + // remove this check. + if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) + { + Send(PowerOffCmd); + _IsCoolingDown = true; + _PowerIsOn = false; + PowerIsOnFeedback.FireUpdate(); + IsCoolingDownFeedback.FireUpdate(); + // Fake cool-down cycle + CooldownTimer = new CTimer(o => + { + Debug.Console(2, this, "Cooldown timer ending"); + _IsCoolingDown = false; + IsCoolingDownFeedback.FireUpdate(); + }, CooldownTime); + } + } + + public override void PowerToggle() + { + if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue) + PowerOff(); + else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue) + PowerOn(); + } + + public void InputHdmi1() + { + Send(Hdmi1Cmd); + } + + public void InputHdmi2() + { + Send(Hdmi2Cmd); + } + + public void InputHdmi3() + { + Send(Hdmi3Cmd); + } + + public void InputHdmi4() + { + Send(Hdmi4Cmd); + } + + public void InputDisplayPort1() + { + Send(Dp1Cmd); + } + + public void InputDisplayPort2() + { + Send(Dp2Cmd); + } + + public void InputDvi1() + { + Send(Dvi1Cmd); + } + + public void InputVideo1() + { + Send(Video1Cmd); + } + + public void InputVga() + { + Send(VgaCmd); + } + + public void InputRgb() + { + Send(RgbCmd); + } + + public override void ExecuteSwitch(object selector) + { + if (selector is Action) + (selector as Action).Invoke(); + else + Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType()); + //Send((string)selector); + } + + void SetVolume(ushort level) + { + var levelString = string.Format("{0}{1:X4}\x03", VolumeLevelPartialCmd, level); + AppendChecksumAndSend(levelString); + //Debug.Console(2, this, "Volume:{0}", ComTextHelper.GetEscapedText(levelString)); + _VolumeLevel = level; + VolumeLevelFeedback.FireUpdate(); + } + + #region IBasicVolumeWithFeedback Members + + public IntFeedback VolumeLevelFeedback { get; private set; } + + public BoolFeedback MuteFeedback { get; private set; } + + public void MuteOff() + { + Send(MuteOffCmd); + } + + public void MuteOn() + { + Send(MuteOnCmd); + } + + void IBasicVolumeWithFeedback.SetVolume(ushort level) + { + SetVolume(level); + } + + #endregion + + #region IBasicVolumeControls Members + + public void MuteToggle() + { + Send(MuteToggleIrCmd); + } + + public void VolumeDown(bool pressRelease) + { + //throw new NotImplementedException(); +//#warning need incrementer for these + SetVolume(_VolumeLevel++); + } + + public void VolumeUp(bool pressRelease) + { + //throw new NotImplementedException(); + SetVolume(_VolumeLevel--); + } + + #endregion + } +} \ No newline at end of file diff --git a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index c30380a8..f2de7d91 100644 --- a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -93,6 +93,7 @@ + diff --git a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo index 1eac3b58..faf56049 100644 Binary files a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo and b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo differ diff --git a/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo b/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo index af89359b..fc218d04 100644 Binary files a/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo and b/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo differ diff --git a/Essentials/PepperDashEssentials/UI Drivers/EssentialsHuddlePanelAvFunctionsDriver.cs b/Essentials/PepperDashEssentials/UI Drivers/EssentialsHuddlePanelAvFunctionsDriver.cs index a117a423..721b2524 100644 --- a/Essentials/PepperDashEssentials/UI Drivers/EssentialsHuddlePanelAvFunctionsDriver.cs +++ b/Essentials/PepperDashEssentials/UI Drivers/EssentialsHuddlePanelAvFunctionsDriver.cs @@ -1,244 +1,244 @@ -using System; -using System.Collections.Generic; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; - -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.SmartObjects; -using PepperDash.Essentials.Core.PageManagers; - -namespace PepperDash.Essentials -{ - /// - /// - /// - public class EssentialsHuddlePanelAvFunctionsDriver : PanelDriverBase - { - CrestronTouchpanelPropertiesConfig Config; - - public enum UiDisplayMode - { - PresentationMode, AudioSetup - } - - /// - /// Whether volume ramping from this panel will show the volume - /// gauge popup. - /// - public bool ShowVolumeGauge { get; set; } - - /// - /// The amount of time that the volume buttons stays on screen, in ms - /// - public uint VolumeButtonPopupTimeout - { - get { return VolumeButtonsPopupFeedback.TimeoutMs; } - set { VolumeButtonsPopupFeedback.TimeoutMs = value; } - } - - /// - /// The amount of time that the volume gauge stays on screen, in ms - /// - public uint VolumeGaugePopupTimeout - { - get { return VolumeGaugeFeedback.TimeoutMs; } - set { VolumeGaugeFeedback.TimeoutMs = value; } - } - - /// - /// - /// - public uint PowerOffTimeout { get; set; } - - /// - /// - /// - public string DefaultRoomKey - { - get { return _DefaultRoomKey; } - set - { - _DefaultRoomKey = value; - CurrentRoom = DeviceManager.GetDeviceForKey(value) as EssentialsHuddleSpaceRoom; - } - } - string _DefaultRoomKey; - - /// - /// - /// - public EssentialsHuddleSpaceRoom CurrentRoom - { - get { return _CurrentRoom; } - set - { - SetCurrentRoom(value); - } - } - EssentialsHuddleSpaceRoom _CurrentRoom; - - /// - /// For hitting feedback - /// - BoolInputSig ShareButtonSig; - BoolInputSig EndMeetingButtonSig; - - /// - /// Controls the extended period that the volume gauge shows on-screen, - /// as triggered by Volume up/down operations - /// - BoolFeedbackPulseExtender VolumeGaugeFeedback; - - /// - /// Controls the period that the volume buttons show on non-hard-button - /// interfaces - /// - BoolFeedbackPulseExtender VolumeButtonsPopupFeedback; - - /// - /// The parent driver for this - /// - PanelDriverBase Parent; - - /// - /// All children attached to this driver. For hiding and showing as a group. - /// - List ChildDrivers = new List(); - - List CurrentDisplayModeSigsInUse = new List(); - - //// Important smart objects - - /// - /// Smart Object 3200 - /// - SubpageReferenceList SourcesSrl; - - /// - /// Smart Object 15022 - /// - SubpageReferenceList ActivityFooterSrl; - - /// - /// Tracks which audio page group the UI is in - /// - UiDisplayMode CurrentDisplayMode; - - /// - /// The AV page mangagers that have been used, to keep them alive for later - /// - Dictionary PageManagers = new Dictionary(); - - /// - /// Current page manager running for a source - /// - PageManager CurrentSourcePageManager; - - /// - /// Will auto-timeout a power off - /// - CTimer PowerOffTimer; - - /// - /// Constructor - /// - public EssentialsHuddlePanelAvFunctionsDriver(PanelDriverBase parent, CrestronTouchpanelPropertiesConfig config) - : base(parent.TriList) - { - Config = config; - Parent = parent; - - //SelectASourceVisibleFeedback = new BoolFeedback(() => - // CurrentRoom != null && !CurrentRoom.OnFeedback.BoolValue && this.IsVisible); - - //SourcesDynamicList = new SmartObjectDynamicList( - // TriList.SmartObjects[UISmartObjectJoin.SourceList], true, 3200); - - SourcesSrl = new SubpageReferenceList(TriList, 3200, 3, 3, 3); - ActivityFooterSrl = new SubpageReferenceList(TriList, 15022, 3, 3, 3); - SetupActivityFooterWhenRoomOff(); - - ShowVolumeGauge = true; - - // One-second pulse extender for volume gauge - VolumeGaugeFeedback = new BoolFeedbackPulseExtender(1500); - VolumeGaugeFeedback.Feedback - .LinkInputSig(TriList.BooleanInput[UIBoolJoin.VolumeGaugePopupVisible]); - - VolumeButtonsPopupFeedback = new BoolFeedbackPulseExtender(4000); - VolumeButtonsPopupFeedback.Feedback - .LinkInputSig(TriList.BooleanInput[UIBoolJoin.VolumeButtonPopupVisible]); - - PowerOffTimeout = 30000; - - TriList.StringInput[UIStringJoin.StartActivityText].StringValue = - "Tap Share to begin"; - } - - /// - /// - /// - public override void Show() +using System; +using System.Collections.Generic; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.SmartObjects; +using PepperDash.Essentials.Core.PageManagers; + +namespace PepperDash.Essentials +{ + /// + /// + /// + public class EssentialsHuddlePanelAvFunctionsDriver : PanelDriverBase + { + CrestronTouchpanelPropertiesConfig Config; + + public enum UiDisplayMode + { + PresentationMode, AudioSetup + } + + /// + /// Whether volume ramping from this panel will show the volume + /// gauge popup. + /// + public bool ShowVolumeGauge { get; set; } + + /// + /// The amount of time that the volume buttons stays on screen, in ms + /// + public uint VolumeButtonPopupTimeout + { + get { return VolumeButtonsPopupFeedback.TimeoutMs; } + set { VolumeButtonsPopupFeedback.TimeoutMs = value; } + } + + /// + /// The amount of time that the volume gauge stays on screen, in ms + /// + public uint VolumeGaugePopupTimeout + { + get { return VolumeGaugeFeedback.TimeoutMs; } + set { VolumeGaugeFeedback.TimeoutMs = value; } + } + + /// + /// + /// + public uint PowerOffTimeout { get; set; } + + /// + /// + /// + public string DefaultRoomKey + { + get { return _DefaultRoomKey; } + set + { + _DefaultRoomKey = value; + CurrentRoom = DeviceManager.GetDeviceForKey(value) as EssentialsHuddleSpaceRoom; + } + } + string _DefaultRoomKey; + + /// + /// + /// + public EssentialsHuddleSpaceRoom CurrentRoom + { + get { return _CurrentRoom; } + set + { + SetCurrentRoom(value); + } + } + EssentialsHuddleSpaceRoom _CurrentRoom; + + /// + /// For hitting feedback + /// + BoolInputSig ShareButtonSig; + BoolInputSig EndMeetingButtonSig; + + /// + /// Controls the extended period that the volume gauge shows on-screen, + /// as triggered by Volume up/down operations + /// + BoolFeedbackPulseExtender VolumeGaugeFeedback; + + /// + /// Controls the period that the volume buttons show on non-hard-button + /// interfaces + /// + BoolFeedbackPulseExtender VolumeButtonsPopupFeedback; + + /// + /// The parent driver for this + /// + PanelDriverBase Parent; + + /// + /// All children attached to this driver. For hiding and showing as a group. + /// + List ChildDrivers = new List(); + + List CurrentDisplayModeSigsInUse = new List(); + + //// Important smart objects + + /// + /// Smart Object 3200 + /// + SubpageReferenceList SourcesSrl; + + /// + /// Smart Object 15022 + /// + SubpageReferenceList ActivityFooterSrl; + + /// + /// Tracks which audio page group the UI is in + /// + UiDisplayMode CurrentDisplayMode; + + /// + /// The AV page mangagers that have been used, to keep them alive for later + /// + Dictionary PageManagers = new Dictionary(); + + /// + /// Current page manager running for a source + /// + PageManager CurrentSourcePageManager; + + /// + /// Will auto-timeout a power off + /// + CTimer PowerOffTimer; + + /// + /// Constructor + /// + public EssentialsHuddlePanelAvFunctionsDriver(PanelDriverBase parent, CrestronTouchpanelPropertiesConfig config) + : base(parent.TriList) + { + Config = config; + Parent = parent; + + //SelectASourceVisibleFeedback = new BoolFeedback(() => + // CurrentRoom != null && !CurrentRoom.OnFeedback.BoolValue && this.IsVisible); + + //SourcesDynamicList = new SmartObjectDynamicList( + // TriList.SmartObjects[UISmartObjectJoin.SourceList], true, 3200); + + SourcesSrl = new SubpageReferenceList(TriList, 3200, 3, 3, 3); + ActivityFooterSrl = new SubpageReferenceList(TriList, 15022, 3, 3, 3); + SetupActivityFooterWhenRoomOff(); + + ShowVolumeGauge = true; + + // One-second pulse extender for volume gauge + VolumeGaugeFeedback = new BoolFeedbackPulseExtender(1500); + VolumeGaugeFeedback.Feedback + .LinkInputSig(TriList.BooleanInput[UIBoolJoin.VolumeGaugePopupVisible]); + + VolumeButtonsPopupFeedback = new BoolFeedbackPulseExtender(4000); + VolumeButtonsPopupFeedback.Feedback + .LinkInputSig(TriList.BooleanInput[UIBoolJoin.VolumeButtonPopupVisible]); + + PowerOffTimeout = 30000; + + TriList.StringInput[UIStringJoin.StartActivityText].StringValue = + "Tap Share to begin"; + } + + /// + /// + /// + public override void Show() { if(CurrentRoom != null) - CurrentRoom.OnFeedback.OutputChange += new EventHandler(OnFeedback_OutputChange); - - TriList.BooleanInput[UIBoolJoin.TopBarVisible].BoolValue = true; - TriList.BooleanInput[UIBoolJoin.ActivityFooterVisible].BoolValue = true; - - // Default to showing rooms/sources now. - ShowMode(UiDisplayMode.PresentationMode); - - // Attach actions - TriList.SetSigFalseAction(UIBoolJoin.VolumeButtonPopupPress, VolumeButtonsTogglePress); - - //Interlocked modals - TriList.SetSigFalseAction(UIBoolJoin.InterlockedModalClosePress, HideCurrentInterlockedModal); - TriList.SetSigFalseAction(UIBoolJoin.HelpPress, () => - { - string message = null; - var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey) - as EssentialsHuddleSpaceRoom; - if (room != null) - message = room.Config.HelpMessage; - else - message = "Sorry, no help message available. No room connected."; - TriList.StringInput[UIStringJoin.HelpMessage].StringValue = message; - ShowInterlockedModal(UIBoolJoin.HelpPageVisible); - }); - - TriList.SetSigFalseAction(UIBoolJoin.RoomHeaderButtonPress, () => - ShowInterlockedModal(UIBoolJoin.RoomHeaderPageVisible)); - -#warning Add press and hold to gear button here - TriList.SetSigFalseAction(UIBoolJoin.GearHeaderButtonPress, () => - ShowInterlockedModal(UIBoolJoin.VolumesPageVisible)); - - // power-related functions - // Note: some of these are not directly-related to the huddle space UI, but are held over - // in case - TriList.SetSigFalseAction(UIBoolJoin.ShowPowerOffPress, PowerButtonPressed); - TriList.SetSigFalseAction(UIBoolJoin.PowerOffCancelPress, CancelPowerOff); - TriList.SetSigFalseAction(UIBoolJoin.PowerOffConfirmPress, FinishPowerOff); - TriList.SetSigFalseAction(UIBoolJoin.PowerOffMorePress, () => - { - CancelPowerOffTimer(); - TriList.BooleanInput[UIBoolJoin.PowerOffStep1Visible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.PowerOffStep2Visible].BoolValue = true; - }); - TriList.SetSigFalseAction(UIBoolJoin.AllRoomsOffPress, () => - { - EssentialsHuddleSpaceRoom.AllRoomsOff(); - CancelPowerOff(); - }); - TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () => - { - if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IPower) - (CurrentRoom.DefaultDisplay as IPower).PowerToggle(); - }); - - base.Show(); + CurrentRoom.OnFeedback.OutputChange += new EventHandler(OnFeedback_OutputChange); + + TriList.BooleanInput[UIBoolJoin.TopBarVisible].BoolValue = true; + TriList.BooleanInput[UIBoolJoin.ActivityFooterVisible].BoolValue = true; + + // Default to showing rooms/sources now. + ShowMode(UiDisplayMode.PresentationMode); + + // Attach actions + TriList.SetSigFalseAction(UIBoolJoin.VolumeButtonPopupPress, VolumeButtonsTogglePress); + + //Interlocked modals + TriList.SetSigFalseAction(UIBoolJoin.InterlockedModalClosePress, HideCurrentInterlockedModal); + TriList.SetSigFalseAction(UIBoolJoin.HelpPress, () => + { + string message = null; + var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey) + as EssentialsHuddleSpaceRoom; + if (room != null) + message = room.Config.HelpMessage; + else + message = "Sorry, no help message available. No room connected."; + TriList.StringInput[UIStringJoin.HelpMessage].StringValue = message; + ShowInterlockedModal(UIBoolJoin.HelpPageVisible); + }); + + TriList.SetSigFalseAction(UIBoolJoin.RoomHeaderButtonPress, () => + ShowInterlockedModal(UIBoolJoin.RoomHeaderPageVisible)); + +#warning Add press and hold to gear button here + TriList.SetSigFalseAction(UIBoolJoin.GearHeaderButtonPress, () => + ShowInterlockedModal(UIBoolJoin.VolumesPageVisible)); + + // power-related functions + // Note: some of these are not directly-related to the huddle space UI, but are held over + // in case + TriList.SetSigFalseAction(UIBoolJoin.ShowPowerOffPress, PowerButtonPressed); + TriList.SetSigFalseAction(UIBoolJoin.PowerOffCancelPress, CancelPowerOff); + TriList.SetSigFalseAction(UIBoolJoin.PowerOffConfirmPress, FinishPowerOff); + TriList.SetSigFalseAction(UIBoolJoin.PowerOffMorePress, () => + { + CancelPowerOffTimer(); + TriList.BooleanInput[UIBoolJoin.PowerOffStep1Visible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.PowerOffStep2Visible].BoolValue = true; + }); + TriList.SetSigFalseAction(UIBoolJoin.AllRoomsOffPress, () => + { + EssentialsHuddleSpaceRoom.AllRoomsOff(); + CancelPowerOff(); + }); + TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () => + { + if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IPower) + (CurrentRoom.DefaultDisplay as IPower).PowerToggle(); + }); + + base.Show(); } void OnFeedback_OutputChange(object sender, EventArgs e) @@ -253,574 +253,574 @@ namespace PepperDash.Essentials TriList.BooleanInput[UIBoolJoin.VolumeSingleMute1Visible].BoolValue = false; TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = false; } - } - - public override void Hide() + } + + public override void Hide() { if (CurrentRoom != null) - CurrentRoom.OnFeedback.OutputChange -= OnFeedback_OutputChange; - - HideAndClearCurrentDisplayModeSigsInUse(); - TriList.BooleanInput[UIBoolJoin.TopBarVisible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.ActivityFooterVisible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; - //TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = false; - VolumeButtonsPopupFeedback.ClearNow(); - CancelPowerOff(); - - base.Hide(); - } - - /// - /// Shows the various "modes" that this driver controls. Presentation, Setup page - /// - /// - public void ShowMode(UiDisplayMode mode) - { - //Clear whatever is showing now. - HideAndClearCurrentDisplayModeSigsInUse(); - CurrentDisplayMode = mode; - switch (mode) - { - case UiDisplayMode.PresentationMode: - // show start page or staging... - if (CurrentRoom.OnFeedback.BoolValue) - { - TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = true; - TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; - } - else - { - TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = true; - TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = true; - TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; - } - // Date/time - if (Config.ShowDate && Config.ShowTime) - { - TriList.BooleanInput[UIBoolJoin.DateAndTimeVisible].BoolValue = true; - TriList.BooleanInput[UIBoolJoin.DateOnlyVisible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.TimeOnlyVisible].BoolValue = false; - } - else - { - TriList.BooleanInput[UIBoolJoin.DateAndTimeVisible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.DateOnlyVisible].BoolValue = Config.ShowDate; - TriList.BooleanInput[UIBoolJoin.TimeOnlyVisible].BoolValue = Config.ShowTime; - } - - ShowCurrentDisplayModeSigsInUse(); - break; - } - } - - /// - /// When the room is off, set the footer SRL - /// - void SetupActivityFooterWhenRoomOff() - { - ActivityFooterSrl.Clear(); - ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl, 0, - b => { if (!b) ShareButtonPressed(); })); - ActivityFooterSrl.Count = 1; - TriList.UShortInput[UIUshortJoin.PresentationListCaretMode].UShortValue = 0; - } - - /// - /// Sets up the footer SRL for when the room is on - /// - void SetupActivityFooterWhenRoomOn() - { - ActivityFooterSrl.Clear(); - ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl, - 0, null)); - ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(2, ActivityFooterSrl, - 3, b => { if (!b) PowerButtonPressed(); })); - ActivityFooterSrl.Count = 2; - TriList.UShortInput[UIUshortJoin.PresentationListCaretMode].UShortValue = 1; - EndMeetingButtonSig = ActivityFooterSrl.BoolInputSig(2, 1); - } - - /// - /// Attached to activity list share button - /// - void ShareButtonPressed() - { - ShareButtonSig = ActivityFooterSrl.BoolInputSig(1, 1); - if (!_CurrentRoom.OnFeedback.BoolValue) - { - ShareButtonSig.BoolValue = true; - TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = true; - TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = true; - } - } - - uint CurrentInterlockedModalJoin; - - void ShowInterlockedModal(uint join) - { - if (CurrentInterlockedModalJoin == join) - HideCurrentInterlockedModal(); - else - { - TriList.BooleanInput[UIBoolJoin.HelpPageVisible].BoolValue = join == UIBoolJoin.HelpPageVisible; - TriList.BooleanInput[UIBoolJoin.RoomHeaderPageVisible].BoolValue = join == UIBoolJoin.RoomHeaderPageVisible; - TriList.BooleanInput[UIBoolJoin.VolumesPageVisible].BoolValue = join == UIBoolJoin.VolumesPageVisible; - CurrentInterlockedModalJoin = join; - } - } - - void HideCurrentInterlockedModal() - { - TriList.BooleanInput[CurrentInterlockedModalJoin].BoolValue = false; - CurrentInterlockedModalJoin = 0; - } - - - /// - /// Shows all sigs that are in CurrentDisplayModeSigsInUse - /// - void ShowCurrentDisplayModeSigsInUse() - { - foreach (var sig in CurrentDisplayModeSigsInUse) - sig.BoolValue = true; - } - - /// - /// Hides all CurrentDisplayModeSigsInUse sigs and clears the array - /// - void HideAndClearCurrentDisplayModeSigsInUse() - { - foreach (var sig in CurrentDisplayModeSigsInUse) - sig.BoolValue = false; - CurrentDisplayModeSigsInUse.Clear(); - } - - /// - /// Send the UI back depending on location, not used in huddle UI - /// - public override void BackButtonPressed() - { - switch (CurrentDisplayMode) - { - case UiDisplayMode.PresentationMode: - //CancelReturnToSourceTimer(); - BackToHome(); - break; - } - } - - /// - /// - /// - void BackToHome() - { - Hide(); - Parent.Show(); - } - - /// - /// Loads the appropriate Sigs into CurrentDisplayModeSigsInUse and shows them - /// - void ShowCurrentSource() - { - if (CurrentRoom.CurrentSourceInfo == null) - return; - - var uiDev = CurrentRoom.CurrentSourceInfo.SourceDevice as IUiDisplayInfo; - PageManager pm = null; - // If we need a page manager, get an appropriate one - if (uiDev != null) - { - TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; - // Got an existing page manager, get it - if (PageManagers.ContainsKey(uiDev)) - pm = PageManagers[uiDev]; - // Otherwise make an apporiate one - else if (uiDev is ISetTopBoxControls) - //pm = new SetTopBoxMediumPageManager(uiDev as ISetTopBoxControls, TriList); - pm = new SetTopBoxThreePanelPageManager(uiDev as ISetTopBoxControls, TriList); - else if (uiDev is IDiscPlayerControls) - pm = new DiscPlayerMediumPageManager(uiDev as IDiscPlayerControls, TriList); - else - pm = new DefaultPageManager(uiDev, TriList); - PageManagers[uiDev] = pm; - CurrentSourcePageManager = pm; - pm.Show(); - } - } - - /// - /// Called from button presses on source, where We can assume we want - /// to change to the proper screen. - /// - /// The key name of the route to run - void UiSelectSource(string key) - { - // Run the route and when it calls back, show the source - CurrentRoom.RunRouteAction(key, null); - } - - /// - /// - /// - public void PowerButtonPressed() - { - if (!CurrentRoom.OnFeedback.BoolValue) - return; - EndMeetingButtonSig.BoolValue = true; - ShareButtonSig.BoolValue = false; - // Timeout or button 1 press will shut down - var modal = new ModalDialog(TriList); - uint time = 60000; - uint seconds = time / 1000; - var message = string.Format("Meeting will end in {0} seconds", seconds); - modal.PresentModalTimerDialog(2, "End Meeting", "Power", message, - "End Meeting Now", "Cancel", time, true, - but => - { - if (but != 2) - CurrentRoom.RunRouteAction("roomOff"); - else - ShareButtonSig.BoolValue = true; // restore Share fb - EndMeetingButtonSig.BoolValue = false; - }); - } - - void CancelPowerOffTimer() - { - if (PowerOffTimer != null) - { - PowerOffTimer.Stop(); - PowerOffTimer = null; - } - } - - /// - /// Runs the power off function on the current room - /// - public void FinishPowerOff() - { - if (CurrentRoom == null) - return; - CurrentRoom.RunRouteAction("roomOff"); - CancelPowerOff(); - } - - /// - /// Hides power off pages and stops timer - /// - void CancelPowerOff() - { - CancelPowerOffTimer(); - TriList.BooleanInput[UIBoolJoin.PowerOffStep1Visible].BoolValue = false; - TriList.BooleanInput[UIBoolJoin.PowerOffStep2Visible].BoolValue = false; - } - - /// - /// - /// - void VolumeButtonsTogglePress() - { - if (VolumeButtonsPopupFeedback.BoolValue) - VolumeButtonsPopupFeedback.ClearNow(); - else - { - // Trigger the popup - VolumeButtonsPopupFeedback.BoolValue = true; - VolumeButtonsPopupFeedback.BoolValue = false; - } - } - - /// - /// - /// - /// - public void VolumeUpPress(bool state) - { - // extend timeouts - if (ShowVolumeGauge) - VolumeGaugeFeedback.BoolValue = state; - VolumeButtonsPopupFeedback.BoolValue = state; - if (CurrentRoom.CurrentVolumeControls != null) - CurrentRoom.CurrentVolumeControls.VolumeUp(state); - } - - /// - /// - /// - /// - public void VolumeDownPress(bool state) - { - // extend timeouts - if (ShowVolumeGauge) - VolumeGaugeFeedback.BoolValue = state; - VolumeButtonsPopupFeedback.BoolValue = state; - if (CurrentRoom.CurrentVolumeControls != null) - CurrentRoom.CurrentVolumeControls.VolumeDown(state); - } - - /// - /// Helper for property setter. Sets the panel to the given room, latching up all functionality - /// - void SetCurrentRoom(EssentialsHuddleSpaceRoom room) - { - if (_CurrentRoom == room) return; - if (_CurrentRoom != null) - { - // Disconnect current room - _CurrentRoom.OnFeedback.OutputChange -= _CurrentRoom_OnFeedback_OutputChange; - _CurrentRoom.CurrentVolumeDeviceChange -= this._CurrentRoom_CurrentAudioDeviceChange; - ClearAudioDeviceConnections(); - _CurrentRoom.CurrentSingleSourceChange -= this._CurrentRoom_SourceInfoChange; - DisconnectSource(_CurrentRoom.CurrentSourceInfo); - } - _CurrentRoom = room; - - if (_CurrentRoom != null) - { - // get the source list config and set up the source list - var config = ConfigReader.ConfigObject.SourceLists; - if (config.ContainsKey(_CurrentRoom.SourceListKey)) - { - var srcList = config[_CurrentRoom.SourceListKey]; - // Setup sources list - uint i = 1; // counter for UI list - foreach (var kvp in srcList) - { - var srcConfig = kvp.Value; - if (!srcConfig.IncludeInSourceList) // Skip sources marked this way - continue; - - var actualSource = DeviceManager.GetDeviceForKey(srcConfig.SourceKey) as Device; - if (actualSource == null) - { - Debug.Console(0, "Cannot assign missing source '{0}' to source UI list", - srcConfig.SourceKey); - continue; - } - var routeKey = kvp.Key; - var item = new SubpageReferenceListSourceItem(i++, SourcesSrl, srcConfig, - b => { if (!b) UiSelectSource(routeKey); }); - SourcesSrl.AddItem(item); // add to the SRL - item.RegisterForSourceChange(_CurrentRoom); - } - SourcesSrl.Count = (ushort)(i - 1); - } - - TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = _CurrentRoom.Name; - - // Link up all the change events from the room - _CurrentRoom.OnFeedback.OutputChange += _CurrentRoom_OnFeedback_OutputChange; - _CurrentRoom.CurrentVolumeDeviceChange += _CurrentRoom_CurrentAudioDeviceChange; - RefreshAudioDeviceConnections(); - _CurrentRoom.CurrentSingleSourceChange += _CurrentRoom_SourceInfoChange; - RefreshSourceInfo(); - } - else - { - // Clear sigs that need to be - TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = "Select a room"; - } - } - - /// - /// For room on/off changes - /// - void _CurrentRoom_OnFeedback_OutputChange(object sender, EventArgs e) - { - var value = _CurrentRoom.OnFeedback.BoolValue; - TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value; - if (value) - { - SetupActivityFooterWhenRoomOn(); - TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false; - } - else - { - SetupActivityFooterWhenRoomOff(); - TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = true; - } - } - - /// - /// Hides source for provided source info - /// - /// - void DisconnectSource(SourceListItem previousInfo) - { - if (previousInfo == null) return; - - // Hide whatever is showing - if (IsVisible) - { - if (CurrentSourcePageManager != null) - { - CurrentSourcePageManager.Hide(); - CurrentSourcePageManager = null; - } - } - - if (previousInfo == null) return; - var previousDev = previousInfo.SourceDevice; - - // device type interfaces - if (previousDev is ISetTopBoxControls) - (previousDev as ISetTopBoxControls).UnlinkButtons(TriList); - // common interfaces - if (previousDev is IChannel) - (previousDev as IChannel).UnlinkButtons(TriList); - if (previousDev is IColor) - (previousDev as IColor).UnlinkButtons(TriList); - if (previousDev is IDPad) - (previousDev as IDPad).UnlinkButtons(TriList); - if (previousDev is IDvr) - (previousDev as IDvr).UnlinkButtons(TriList); - if (previousDev is INumericKeypad) - (previousDev as INumericKeypad).UnlinkButtons(TriList); - if (previousDev is IPower) - (previousDev as IPower).UnlinkButtons(TriList); - if (previousDev is ITransport) - (previousDev as ITransport).UnlinkButtons(TriList); - //if (previousDev is IRadio) - // (previousDev as IRadio).UnlinkButtons(this); - } - - /// - /// Refreshes and shows the room's current source - /// - void RefreshSourceInfo() - { - var routeInfo = CurrentRoom.CurrentSourceInfo; - // This will show off popup too - if (this.IsVisible) - ShowCurrentSource(); - - if (routeInfo == null || !CurrentRoom.OnFeedback.BoolValue) - { - // Check for power off and insert "Room is off" - TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = "Room is off"; - TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = "Power"; - this.Hide(); - Parent.Show(); - return; - } - else if (CurrentRoom.CurrentSourceInfo != null) - { - TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = routeInfo.PreferredName; - TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = routeInfo.Icon; // defaults to "blank" - } - else - { - TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = "---"; - TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = "Blank"; - } - - // Connect controls - if (routeInfo.SourceDevice != null) - ConnectControlDeviceMethods(routeInfo.SourceDevice); - } - - /// - /// Attach the source to the buttons and things - /// - void ConnectControlDeviceMethods(Device dev) - { - if(dev is ISetTopBoxControls) - (dev as ISetTopBoxControls).LinkButtons(TriList); - if (dev is IChannel) - (dev as IChannel).LinkButtons(TriList); - if (dev is IColor) - (dev as IColor).LinkButtons(TriList); - if (dev is IDPad) - (dev as IDPad).LinkButtons(TriList); - if (dev is IDvr) - (dev as IDvr).LinkButtons(TriList); - if (dev is INumericKeypad) - (dev as INumericKeypad).LinkButtons(TriList); - if (dev is IPower) - (dev as IPower).LinkButtons(TriList); - if (dev is ITransport) - (dev as ITransport).LinkButtons(TriList); - //if (dev is IRadio) - // (dev as IRadio).LinkButtons(this); // +++++++++++++ Make part of this into page manager - - //if (dev is ICustomFunctions) - //{ - // var custBridge = (dev as ICustomFunctions).GetCustomBridge(); - // custBridge.Link(this.Remote); - } - - /// - /// Detaches the buttons and feedback from the room's current audio device - /// - void ClearAudioDeviceConnections() - { - TriList.ClearBoolSigAction(UIBoolJoin.VolumeUpPress); - TriList.ClearBoolSigAction(UIBoolJoin.VolumeDownPress); - TriList.ClearBoolSigAction(UIBoolJoin.Volume1ProgramMutePressAndFB); - - var fDev = CurrentRoom.CurrentVolumeControls as IBasicVolumeWithFeedback; - if (fDev != null) - { - TriList.ClearUShortSigAction(UIUshortJoin.VolumeSlider1Value); - fDev.VolumeLevelFeedback.UnlinkInputSig( - TriList.UShortInput[UIUshortJoin.VolumeSlider1Value]); - } - } - - /// - /// Attaches the buttons and feedback to the room's current audio device - /// - void RefreshAudioDeviceConnections() - { - var dev = CurrentRoom.CurrentVolumeControls; - if (dev != null) // connect buttons - { - TriList.SetBoolSigAction(UIBoolJoin.VolumeUpPress, VolumeUpPress); - TriList.SetBoolSigAction(UIBoolJoin.VolumeDownPress, VolumeDownPress); - TriList.SetSigFalseAction(UIBoolJoin.Volume1ProgramMutePressAndFB, dev.MuteToggle); - } - - var fbDev = dev as IBasicVolumeWithFeedback; - if (fbDev == null) // this should catch both IBasicVolume and IBasicVolumeWithFeeback - TriList.UShortInput[UIUshortJoin.VolumeSlider1Value].UShortValue = 0; - else - { - // slider - TriList.SetUShortSigAction(UIUshortJoin.VolumeSlider1Value, fbDev.SetVolume); - // feedbacks - fbDev.MuteFeedback.LinkInputSig(TriList.BooleanInput[UIBoolJoin.Volume1ProgramMutePressAndFB]); - fbDev.VolumeLevelFeedback.LinkInputSig( - TriList.UShortInput[UIUshortJoin.VolumeSlider1Value]); - } - } - - /// - /// Handler for when the room's volume control device changes - /// - void _CurrentRoom_CurrentAudioDeviceChange(object sender, VolumeDeviceChangeEventArgs args) - { - if (args.Type == ChangeType.WillChange) - ClearAudioDeviceConnections(); - else // did change - RefreshAudioDeviceConnections(); - } - - /// - /// Handles source change - /// - void _CurrentRoom_SourceInfoChange(EssentialsRoomBase room, - SourceListItem info, ChangeType change) - { - if (change == ChangeType.WillChange) - DisconnectSource(info); - else - RefreshSourceInfo(); - } - } + CurrentRoom.OnFeedback.OutputChange -= OnFeedback_OutputChange; + + HideAndClearCurrentDisplayModeSigsInUse(); + TriList.BooleanInput[UIBoolJoin.TopBarVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.ActivityFooterVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; + //TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = false; + VolumeButtonsPopupFeedback.ClearNow(); + CancelPowerOff(); + + base.Hide(); + } + + /// + /// Shows the various "modes" that this driver controls. Presentation, Setup page + /// + /// + public void ShowMode(UiDisplayMode mode) + { + //Clear whatever is showing now. + HideAndClearCurrentDisplayModeSigsInUse(); + CurrentDisplayMode = mode; + switch (mode) + { + case UiDisplayMode.PresentationMode: + // show start page or staging... + if (CurrentRoom.OnFeedback.BoolValue) + { + TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = true; + TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; + } + else + { + TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = true; + TriList.BooleanInput[UIBoolJoin.TapToBeginVisible].BoolValue = true; + TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; + } + // Date/time + if (Config.ShowDate && Config.ShowTime) + { + TriList.BooleanInput[UIBoolJoin.DateAndTimeVisible].BoolValue = true; + TriList.BooleanInput[UIBoolJoin.DateOnlyVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.TimeOnlyVisible].BoolValue = false; + } + else + { + TriList.BooleanInput[UIBoolJoin.DateAndTimeVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.DateOnlyVisible].BoolValue = Config.ShowDate; + TriList.BooleanInput[UIBoolJoin.TimeOnlyVisible].BoolValue = Config.ShowTime; + } + + ShowCurrentDisplayModeSigsInUse(); + break; + } + } + + /// + /// When the room is off, set the footer SRL + /// + void SetupActivityFooterWhenRoomOff() + { + ActivityFooterSrl.Clear(); + ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl, 0, + b => { if (!b) ShareButtonPressed(); })); + ActivityFooterSrl.Count = 1; + TriList.UShortInput[UIUshortJoin.PresentationListCaretMode].UShortValue = 0; + } + + /// + /// Sets up the footer SRL for when the room is on + /// + void SetupActivityFooterWhenRoomOn() + { + ActivityFooterSrl.Clear(); + ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl, + 0, null)); + ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(2, ActivityFooterSrl, + 3, b => { if (!b) PowerButtonPressed(); })); + ActivityFooterSrl.Count = 2; + TriList.UShortInput[UIUshortJoin.PresentationListCaretMode].UShortValue = 1; + EndMeetingButtonSig = ActivityFooterSrl.BoolInputSig(2, 1); + } + + /// + /// Attached to activity list share button + /// + void ShareButtonPressed() + { + ShareButtonSig = ActivityFooterSrl.BoolInputSig(1, 1); + if (!_CurrentRoom.OnFeedback.BoolValue) + { + ShareButtonSig.BoolValue = true; + TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = true; + TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = true; + } + } + + uint CurrentInterlockedModalJoin; + + void ShowInterlockedModal(uint join) + { + if (CurrentInterlockedModalJoin == join) + HideCurrentInterlockedModal(); + else + { + TriList.BooleanInput[UIBoolJoin.HelpPageVisible].BoolValue = join == UIBoolJoin.HelpPageVisible; + TriList.BooleanInput[UIBoolJoin.RoomHeaderPageVisible].BoolValue = join == UIBoolJoin.RoomHeaderPageVisible; + TriList.BooleanInput[UIBoolJoin.VolumesPageVisible].BoolValue = join == UIBoolJoin.VolumesPageVisible; + CurrentInterlockedModalJoin = join; + } + } + + void HideCurrentInterlockedModal() + { + TriList.BooleanInput[CurrentInterlockedModalJoin].BoolValue = false; + CurrentInterlockedModalJoin = 0; + } + + + /// + /// Shows all sigs that are in CurrentDisplayModeSigsInUse + /// + void ShowCurrentDisplayModeSigsInUse() + { + foreach (var sig in CurrentDisplayModeSigsInUse) + sig.BoolValue = true; + } + + /// + /// Hides all CurrentDisplayModeSigsInUse sigs and clears the array + /// + void HideAndClearCurrentDisplayModeSigsInUse() + { + foreach (var sig in CurrentDisplayModeSigsInUse) + sig.BoolValue = false; + CurrentDisplayModeSigsInUse.Clear(); + } + + /// + /// Send the UI back depending on location, not used in huddle UI + /// + public override void BackButtonPressed() + { + switch (CurrentDisplayMode) + { + case UiDisplayMode.PresentationMode: + //CancelReturnToSourceTimer(); + BackToHome(); + break; + } + } + + /// + /// + /// + void BackToHome() + { + Hide(); + Parent.Show(); + } + + /// + /// Loads the appropriate Sigs into CurrentDisplayModeSigsInUse and shows them + /// + void ShowCurrentSource() + { + if (CurrentRoom.CurrentSourceInfo == null) + return; + + var uiDev = CurrentRoom.CurrentSourceInfo.SourceDevice as IUiDisplayInfo; + PageManager pm = null; + // If we need a page manager, get an appropriate one + if (uiDev != null) + { + TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; + // Got an existing page manager, get it + if (PageManagers.ContainsKey(uiDev)) + pm = PageManagers[uiDev]; + // Otherwise make an apporiate one + else if (uiDev is ISetTopBoxControls) + //pm = new SetTopBoxMediumPageManager(uiDev as ISetTopBoxControls, TriList); + pm = new SetTopBoxThreePanelPageManager(uiDev as ISetTopBoxControls, TriList); + else if (uiDev is IDiscPlayerControls) + pm = new DiscPlayerMediumPageManager(uiDev as IDiscPlayerControls, TriList); + else + pm = new DefaultPageManager(uiDev, TriList); + PageManagers[uiDev] = pm; + CurrentSourcePageManager = pm; + pm.Show(); + } + } + + /// + /// Called from button presses on source, where We can assume we want + /// to change to the proper screen. + /// + /// The key name of the route to run + void UiSelectSource(string key) + { + // Run the route and when it calls back, show the source + CurrentRoom.RunRouteAction(key, null); + } + + /// + /// + /// + public void PowerButtonPressed() + { + if (!CurrentRoom.OnFeedback.BoolValue) + return; + EndMeetingButtonSig.BoolValue = true; + ShareButtonSig.BoolValue = false; + // Timeout or button 1 press will shut down + var modal = new ModalDialog(TriList); + uint time = 60000; + uint seconds = time / 1000; + var message = string.Format("Meeting will end in {0} seconds", seconds); + modal.PresentModalTimerDialog(2, "End Meeting", "Power", message, + "End Meeting Now", "Cancel", time, true, + but => + { + if (but != 2) + CurrentRoom.RunRouteAction("roomOff"); + else + ShareButtonSig.BoolValue = true; // restore Share fb + EndMeetingButtonSig.BoolValue = false; + }); + } + + void CancelPowerOffTimer() + { + if (PowerOffTimer != null) + { + PowerOffTimer.Stop(); + PowerOffTimer = null; + } + } + + /// + /// Runs the power off function on the current room + /// + public void FinishPowerOff() + { + if (CurrentRoom == null) + return; + CurrentRoom.RunRouteAction("roomOff"); + CancelPowerOff(); + } + + /// + /// Hides power off pages and stops timer + /// + void CancelPowerOff() + { + CancelPowerOffTimer(); + TriList.BooleanInput[UIBoolJoin.PowerOffStep1Visible].BoolValue = false; + TriList.BooleanInput[UIBoolJoin.PowerOffStep2Visible].BoolValue = false; + } + + /// + /// + /// + void VolumeButtonsTogglePress() + { + if (VolumeButtonsPopupFeedback.BoolValue) + VolumeButtonsPopupFeedback.ClearNow(); + else + { + // Trigger the popup + VolumeButtonsPopupFeedback.BoolValue = true; + VolumeButtonsPopupFeedback.BoolValue = false; + } + } + + /// + /// + /// + /// + public void VolumeUpPress(bool state) + { + // extend timeouts + if (ShowVolumeGauge) + VolumeGaugeFeedback.BoolValue = state; + VolumeButtonsPopupFeedback.BoolValue = state; + if (CurrentRoom.CurrentVolumeControls != null) + CurrentRoom.CurrentVolumeControls.VolumeUp(state); + } + + /// + /// + /// + /// + public void VolumeDownPress(bool state) + { + // extend timeouts + if (ShowVolumeGauge) + VolumeGaugeFeedback.BoolValue = state; + VolumeButtonsPopupFeedback.BoolValue = state; + if (CurrentRoom.CurrentVolumeControls != null) + CurrentRoom.CurrentVolumeControls.VolumeDown(state); + } + + /// + /// Helper for property setter. Sets the panel to the given room, latching up all functionality + /// + void SetCurrentRoom(EssentialsHuddleSpaceRoom room) + { + if (_CurrentRoom == room) return; + if (_CurrentRoom != null) + { + // Disconnect current room + _CurrentRoom.OnFeedback.OutputChange -= _CurrentRoom_OnFeedback_OutputChange; + _CurrentRoom.CurrentVolumeDeviceChange -= this._CurrentRoom_CurrentAudioDeviceChange; + ClearAudioDeviceConnections(); + _CurrentRoom.CurrentSingleSourceChange -= this._CurrentRoom_SourceInfoChange; + DisconnectSource(_CurrentRoom.CurrentSourceInfo); + } + _CurrentRoom = room; + + if (_CurrentRoom != null) + { + // get the source list config and set up the source list + var config = ConfigReader.ConfigObject.SourceLists; + if (config.ContainsKey(_CurrentRoom.SourceListKey)) + { + var srcList = config[_CurrentRoom.SourceListKey]; + // Setup sources list + uint i = 1; // counter for UI list + foreach (var kvp in srcList) + { + var srcConfig = kvp.Value; + if (!srcConfig.IncludeInSourceList) // Skip sources marked this way + continue; + + var actualSource = DeviceManager.GetDeviceForKey(srcConfig.SourceKey) as Device; + if (actualSource == null) + { + Debug.Console(0, "Cannot assign missing source '{0}' to source UI list", + srcConfig.SourceKey); + continue; + } + var routeKey = kvp.Key; + var item = new SubpageReferenceListSourceItem(i++, SourcesSrl, srcConfig, + b => { if (!b) UiSelectSource(routeKey); }); + SourcesSrl.AddItem(item); // add to the SRL + item.RegisterForSourceChange(_CurrentRoom); + } + SourcesSrl.Count = (ushort)(i - 1); + } + + TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = _CurrentRoom.Name; + + // Link up all the change events from the room + _CurrentRoom.OnFeedback.OutputChange += _CurrentRoom_OnFeedback_OutputChange; + _CurrentRoom.CurrentVolumeDeviceChange += _CurrentRoom_CurrentAudioDeviceChange; + RefreshAudioDeviceConnections(); + _CurrentRoom.CurrentSingleSourceChange += _CurrentRoom_SourceInfoChange; + RefreshSourceInfo(); + } + else + { + // Clear sigs that need to be + TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = "Select a room"; + } + } + + /// + /// For room on/off changes + /// + void _CurrentRoom_OnFeedback_OutputChange(object sender, EventArgs e) + { + var value = _CurrentRoom.OnFeedback.BoolValue; + TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value; + if (value) + { + SetupActivityFooterWhenRoomOn(); + TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false; + } + else + { + SetupActivityFooterWhenRoomOff(); + TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = true; + } + } + + /// + /// Hides source for provided source info + /// + /// + void DisconnectSource(SourceListItem previousInfo) + { + if (previousInfo == null) return; + + // Hide whatever is showing + if (IsVisible) + { + if (CurrentSourcePageManager != null) + { + CurrentSourcePageManager.Hide(); + CurrentSourcePageManager = null; + } + } + + if (previousInfo == null) return; + var previousDev = previousInfo.SourceDevice; + + // device type interfaces + if (previousDev is ISetTopBoxControls) + (previousDev as ISetTopBoxControls).UnlinkButtons(TriList); + // common interfaces + if (previousDev is IChannel) + (previousDev as IChannel).UnlinkButtons(TriList); + if (previousDev is IColor) + (previousDev as IColor).UnlinkButtons(TriList); + if (previousDev is IDPad) + (previousDev as IDPad).UnlinkButtons(TriList); + if (previousDev is IDvr) + (previousDev as IDvr).UnlinkButtons(TriList); + if (previousDev is INumericKeypad) + (previousDev as INumericKeypad).UnlinkButtons(TriList); + if (previousDev is IPower) + (previousDev as IPower).UnlinkButtons(TriList); + if (previousDev is ITransport) + (previousDev as ITransport).UnlinkButtons(TriList); + //if (previousDev is IRadio) + // (previousDev as IRadio).UnlinkButtons(this); + } + + /// + /// Refreshes and shows the room's current source + /// + void RefreshSourceInfo() + { + var routeInfo = CurrentRoom.CurrentSourceInfo; + // This will show off popup too + if (this.IsVisible) + ShowCurrentSource(); + + if (routeInfo == null || !CurrentRoom.OnFeedback.BoolValue) + { + // Check for power off and insert "Room is off" + TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = "Room is off"; + TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = "Power"; + this.Hide(); + Parent.Show(); + return; + } + else if (CurrentRoom.CurrentSourceInfo != null) + { + TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = routeInfo.PreferredName; + TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = routeInfo.Icon; // defaults to "blank" + } + else + { + TriList.StringInput[UIStringJoin.CurrentSourceName].StringValue = "---"; + TriList.StringInput[UIStringJoin.CurrentSourceIcon].StringValue = "Blank"; + } + + // Connect controls + if (routeInfo.SourceDevice != null) + ConnectControlDeviceMethods(routeInfo.SourceDevice); + } + + /// + /// Attach the source to the buttons and things + /// + void ConnectControlDeviceMethods(Device dev) + { + if(dev is ISetTopBoxControls) + (dev as ISetTopBoxControls).LinkButtons(TriList); + if (dev is IChannel) + (dev as IChannel).LinkButtons(TriList); + if (dev is IColor) + (dev as IColor).LinkButtons(TriList); + if (dev is IDPad) + (dev as IDPad).LinkButtons(TriList); + if (dev is IDvr) + (dev as IDvr).LinkButtons(TriList); + if (dev is INumericKeypad) + (dev as INumericKeypad).LinkButtons(TriList); + if (dev is IPower) + (dev as IPower).LinkButtons(TriList); + if (dev is ITransport) + (dev as ITransport).LinkButtons(TriList); + //if (dev is IRadio) + // (dev as IRadio).LinkButtons(this); // +++++++++++++ Make part of this into page manager + + //if (dev is ICustomFunctions) + //{ + // var custBridge = (dev as ICustomFunctions).GetCustomBridge(); + // custBridge.Link(this.Remote); + } + + /// + /// Detaches the buttons and feedback from the room's current audio device + /// + void ClearAudioDeviceConnections() + { + TriList.ClearBoolSigAction(UIBoolJoin.VolumeUpPress); + TriList.ClearBoolSigAction(UIBoolJoin.VolumeDownPress); + TriList.ClearBoolSigAction(UIBoolJoin.Volume1ProgramMutePressAndFB); + + var fDev = CurrentRoom.CurrentVolumeControls as IBasicVolumeWithFeedback; + if (fDev != null) + { + TriList.ClearUShortSigAction(UIUshortJoin.VolumeSlider1Value); + fDev.VolumeLevelFeedback.UnlinkInputSig( + TriList.UShortInput[UIUshortJoin.VolumeSlider1Value]); + } + } + + /// + /// Attaches the buttons and feedback to the room's current audio device + /// + void RefreshAudioDeviceConnections() + { + var dev = CurrentRoom.CurrentVolumeControls; + if (dev != null) // connect buttons + { + TriList.SetBoolSigAction(UIBoolJoin.VolumeUpPress, VolumeUpPress); + TriList.SetBoolSigAction(UIBoolJoin.VolumeDownPress, VolumeDownPress); + TriList.SetSigFalseAction(UIBoolJoin.Volume1ProgramMutePressAndFB, dev.MuteToggle); + } + + var fbDev = dev as IBasicVolumeWithFeedback; + if (fbDev == null) // this should catch both IBasicVolume and IBasicVolumeWithFeeback + TriList.UShortInput[UIUshortJoin.VolumeSlider1Value].UShortValue = 0; + else + { + // slider + TriList.SetUShortSigAction(UIUshortJoin.VolumeSlider1Value, fbDev.SetVolume); + // feedbacks + fbDev.MuteFeedback.LinkInputSig(TriList.BooleanInput[UIBoolJoin.Volume1ProgramMutePressAndFB]); + fbDev.VolumeLevelFeedback.LinkInputSig( + TriList.UShortInput[UIUshortJoin.VolumeSlider1Value]); + } + } + + /// + /// Handler for when the room's volume control device changes + /// + void _CurrentRoom_CurrentAudioDeviceChange(object sender, VolumeDeviceChangeEventArgs args) + { + if (args.Type == ChangeType.WillChange) + ClearAudioDeviceConnections(); + else // did change + RefreshAudioDeviceConnections(); + } + + /// + /// Handles source change + /// + void _CurrentRoom_SourceInfoChange(EssentialsRoomBase room, + SourceListItem info, ChangeType change) + { + if (change == ChangeType.WillChange) + DisconnectSource(info); + else + RefreshSourceInfo(); + } + } } \ No newline at end of file