diff --git a/Essentials Core/PepperDashEssentialsBase/SmartObjects/SmartObjectHelperBase.cs b/Essentials Core/PepperDashEssentialsBase/SmartObjects/SmartObjectHelperBase.cs
index 741eec45..6fadf491 100644
--- a/Essentials Core/PepperDashEssentialsBase/SmartObjects/SmartObjectHelperBase.cs
+++ b/Essentials Core/PepperDashEssentialsBase/SmartObjects/SmartObjectHelperBase.cs
@@ -6,6 +6,8 @@ using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
+using PepperDash.Core;
+
namespace PepperDash.Essentials.Core.SmartObjects
{
public class SmartObjectHelperBase
@@ -33,13 +35,37 @@ namespace PepperDash.Essentials.Core.SmartObjects
SmartObject.SigChange -= this.SmartObject_SigChange;
}
+ ///
+ /// Helper to get a sig name with debugging when fail
+ ///
+ ///
+ ///
public BoolOutputSig GetBoolOutputNamed(string name)
{
if (SmartObject.BooleanOutput.Contains(name))
return SmartObject.BooleanOutput[name];
+ else
+ Debug.Console(0, "WARNING: Cannot get signal. Smart object {0} on trilist {1:x2} does not contain signal '{2}'",
+ SmartObject.ID, SmartObject.Device.ID, name);
return null;
}
+ ///
+ /// Sets action on signal after checking for existence.
+ ///
+ ///
+ ///
+ public void SetBoolAction(string name, Action a)
+ {
+ if (SmartObject.BooleanOutput.Contains(name))
+ SmartObject.BooleanOutput[name].UserObject = a;
+ else
+ {
+ Debug.Console(0, "WARNING: Cannot set action. Smart object {0} on trilist {1:x2} does not contain signal '{2}'",
+ SmartObject.ID, SmartObject.Device.ID, name);
+ }
+ }
+
///
/// Standard Action listener
///
diff --git a/Essentials Core/PepperDashEssentialsBase/SmartObjects/SmartObjectNumeric.cs b/Essentials Core/PepperDashEssentialsBase/SmartObjects/SmartObjectNumeric.cs
index 5d234634..7e574242 100644
--- a/Essentials Core/PepperDashEssentialsBase/SmartObjects/SmartObjectNumeric.cs
+++ b/Essentials Core/PepperDashEssentialsBase/SmartObjects/SmartObjectNumeric.cs
@@ -10,6 +10,14 @@ namespace PepperDash.Essentials.Core.SmartObjects
{
public class SmartObjectNumeric : SmartObjectHelperBase
{
+ ///
+ /// Defaults to "Misc_1". The name of the button in VTPro (Usually the text)
+ ///
+ public string Misc1SigName { get; set; }
+ ///
+ /// Defaults to "Misc_2". The name of the button in VTPro (Usually the text)
+ ///
+ public string Misc2SigName { get; set; }
public BoolOutputSig Digit1 { get { return GetBoolOutputNamed("1"); } }
public BoolOutputSig Digit2 { get { return GetBoolOutputNamed("2"); } }
@@ -21,11 +29,13 @@ namespace PepperDash.Essentials.Core.SmartObjects
public BoolOutputSig Digit8 { get { return GetBoolOutputNamed("8"); } }
public BoolOutputSig Digit9 { get { return GetBoolOutputNamed("9"); } }
public BoolOutputSig Digit0 { get { return GetBoolOutputNamed("0"); } }
- public BoolOutputSig Misc1 { get { return GetBoolOutputNamed("Misc_1"); } }
- public BoolOutputSig Misc2 { get { return GetBoolOutputNamed("Misc_2"); } }
+ public BoolOutputSig Misc1 { get { return GetBoolOutputNamed(Misc1SigName); } }
+ public BoolOutputSig Misc2 { get { return GetBoolOutputNamed(Misc2SigName); } }
public SmartObjectNumeric(SmartObject so, bool useUserObjectHandler) : base(so, useUserObjectHandler)
{
+ Misc1SigName = "Misc_1";
+ Misc2SigName = "Misc_2";
}
}
}
\ No newline at end of file
diff --git a/Essentials Core/PepperDashEssentialsBase/SubpageReferencList/SubpageReferenceList.cs b/Essentials Core/PepperDashEssentialsBase/SubpageReferencList/SubpageReferenceList.cs
index 83b0934d..65499990 100644
--- a/Essentials Core/PepperDashEssentialsBase/SubpageReferencList/SubpageReferenceList.cs
+++ b/Essentials Core/PepperDashEssentialsBase/SubpageReferencList/SubpageReferenceList.cs
@@ -53,7 +53,7 @@ namespace PepperDash.Essentials.Core
// Fail cleanly if not defined
if (triList.SmartObjects == null || triList.SmartObjects.Count == 0)
{
- Debug.Console(0, "TriList {0:X2} Smart objects not loaded", triList.ID, smartObjectId);
+ Debug.Console(0, "TriList {0:X2} Smart objects have not been loaded", triList.ID, smartObjectId);
return;
}
if (triList.SmartObjects.TryGetValue(smartObjectId, out obj))
@@ -74,7 +74,8 @@ namespace PepperDash.Essentials.Core
SRL.SigChange += new SmartObjectSigChangeEventHandler(SRL_SigChange);
}
else
- Debug.Console(0, "TriList 0x{0:X2} Cannot load smart object {1}", triList.ID, smartObjectId);
+ Debug.Console(0, "ERROR: TriList 0x{0:X2} Cannot load smart object {1}. Verify correct SGD file is loaded",
+ triList.ID, smartObjectId);
}
///
diff --git a/Essentials Core/PepperDashEssentialsBase/Touchpanels/TriListExtensions.cs b/Essentials Core/PepperDashEssentialsBase/Touchpanels/TriListExtensions.cs
index 690bdacf..be666c5f 100644
--- a/Essentials Core/PepperDashEssentialsBase/Touchpanels/TriListExtensions.cs
+++ b/Essentials Core/PepperDashEssentialsBase/Touchpanels/TriListExtensions.cs
@@ -17,7 +17,8 @@ namespace PepperDash.Essentials.Core
public static class SigAndTriListExtensions
{
///
- /// Attaches Action to Sig's user object and returns the same Sig.
+ /// Attaches Action to Sig's user object and returns the same Sig. This provides no protection
+ /// from null sigs
///
/// The BoolOutputSig to attach the Action to
/// An action to run when sig is pressed and when released
@@ -64,13 +65,20 @@ namespace PepperDash.Essentials.Core
}
///
- ///
+ /// Sets an action to a held sig
///
- ///
- ///
- ///
- ///
+ /// The sig
public static BoolOutputSig SetSigHeldAction(this BasicTriList tl, uint sigNum, uint heldMs, Action heldAction)
+ {
+ return SetSigHeldAction(tl, sigNum, heldMs, heldAction, null);
+ }
+
+
+ ///
+ /// Sets an action to a held sig as well as a released-without-hold action
+ ///
+ /// The sig
+ public static BoolOutputSig SetSigHeldAction(this BasicTriList tl, uint sigNum, uint heldMs, Action heldAction, Action releaseAction)
{
CTimer heldTimer = null;
return tl.SetBoolSigAction(sigNum, press =>
@@ -87,10 +95,12 @@ namespace PepperDash.Essentials.Core
heldAction();
}, heldMs);
}
-
else if (heldTimer != null) // released
+ {
heldTimer.Stop();
- // could also revise this else to fire a released action as well as cancel the timer
+ if (releaseAction != null)
+ releaseAction();
+ }
});
}
@@ -143,5 +153,21 @@ namespace PepperDash.Essentials.Core
{
return ClearSigAction(tl.StringOutput[sigNum]) as StringOutputSig;
}
- }
+
+ ///
+ /// Helper method to set the value of a bool Sig on TriList
+ ///
+ public static void SetBool(this BasicTriList tl, uint sigNum, bool value)
+ {
+ tl.BooleanInput[sigNum].BoolValue = value;
+ }
+
+ ///
+ /// Helper method to set the value of a string Sig on TriList
+ ///
+ public static void SetString(this BasicTriList tl, uint sigNum, string value)
+ {
+ tl.StringInput[sigNum].StringValue = value;
+ }
+ }
}
\ 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 adf18e16..f7a4fab5 100644
--- a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
+++ b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
@@ -127,10 +127,7 @@
-
-
-
-
+
diff --git a/Essentials Devices Common/Essentials Devices Common/VC/MockVC/MockVC.cs b/Essentials Devices Common/Essentials Devices Common/VC/MockVC/MockVC.cs
new file mode 100644
index 00000000..d8f11150
--- /dev/null
+++ b/Essentials Devices Common/Essentials Devices Common/VC/MockVC/MockVC.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials.Devices.Common.VideoCodec
+{
+ public class MockVC : VideoCodecBase
+ {
+ public MockVC(string key, string name)
+ : base(key, name)
+ {
+
+ }
+
+ protected override Func InCallFeedbackFunc
+ {
+ get { return () => _InCall; }
+ }
+ bool _InCall;
+
+ protected override Func IncomingCallFeedbackFunc
+ {
+ get { return () => _IncomingCall; }
+ }
+ bool _IncomingCall;
+
+ protected override Func TransmitMuteFeedbackFunc
+ {
+ get { return () => _TransmitMute; }
+ }
+ bool _TransmitMute;
+
+ protected override Func ReceiveMuteFeedbackFunc
+ {
+ get { return () => _ReceiveMute; }
+ }
+ bool _ReceiveMute;
+
+ protected override Func PrivacyModeFeedbackFunc
+ {
+ get { return () => _PrivacyModeIsOn; }
+ }
+ bool _PrivacyModeIsOn;
+
+ ///
+ /// Dials, yo!
+ ///
+ public override void Dial(string s)
+ {
+
+ _InCall = true;
+ InCallFeedback.FireUpdate();
+ }
+
+ ///
+ /// Makes horrible tones go out on the wire!
+ ///
+ ///
+ public void SendDTMF(string s)
+ {
+
+ }
+
+
+ public override void EndCall()
+ {
+ _InCall = false;
+ InCallFeedback.FireUpdate();
+ }
+
+ ///
+ /// For a call from the test methods below
+ ///
+ public override void AcceptCall()
+ {
+
+ }
+
+ ///
+ /// For a call from the test methods below
+ ///
+ public override void RejectCall()
+ {
+
+ }
+
+
+
+ public override void ExecuteSwitch(object selector)
+ {
+
+ }
+
+ public override void ReceiveMuteOff()
+ {
+ if (!_ReceiveMute)
+ return;
+ _ReceiveMute = false;
+ ReceiveMuteIsOnFeedback.FireUpdate();
+ }
+
+ public override void ReceiveMuteOn()
+ {
+ if (_ReceiveMute)
+ return;
+ ReceiveMuteIsOnFeedback.FireUpdate();
+ }
+
+ public override void ReceiveMuteToggle()
+ {
+ _ReceiveMute = !_ReceiveMute;
+ ReceiveMuteIsOnFeedback.FireUpdate();
+ }
+
+ public override void SetReceiveVolume(ushort level)
+ {
+
+ }
+
+ public override void TransmitMuteOff()
+ {
+ if (!_TransmitMute)
+ return;
+ _TransmitMute = false;
+ TransmitMuteIsOnFeedback.FireUpdate();
+ }
+
+ public override void TransmitMuteOn()
+ {
+ if (_TransmitMute)
+ return;
+ TransmitMuteIsOnFeedback.FireUpdate();
+ }
+
+ public override void TransmitMuteToggle()
+ {
+ _TransmitMute = !_TransmitMute;
+ TransmitMuteIsOnFeedback.FireUpdate();
+ }
+
+ public override void SetTransmitVolume(ushort level)
+ {
+
+ }
+
+ public override void PrivacyModeOn()
+ {
+ if (_PrivacyModeIsOn)
+ return;
+ _PrivacyModeIsOn = true;
+ PrivacyModeIsOnFeedback.FireUpdate();
+
+ }
+
+ public override void PrivacyModeOff()
+ {
+ if (!_PrivacyModeIsOn)
+ return;
+ _PrivacyModeIsOn = false;
+ PrivacyModeIsOnFeedback.FireUpdate();
+ }
+
+ public override void PrivacyModeToggle()
+ {
+ _PrivacyModeIsOn = !_PrivacyModeIsOn;
+ PrivacyModeIsOnFeedback.FireUpdate();
+ }
+
+ //********************************************************
+ // SIMULATION METHODS
+
+ public void TestIncomingCall(string url)
+ {
+ _IncomingCall = true;
+ IncomingCallFeedback.FireUpdate();
+ }
+
+ public void TestFarEndHangup()
+ {
+
+ }
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs b/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs
index b9ba2bc8..34d2f516 100644
--- a/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs
+++ b/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
-using Crestron.SimplSharp.CrestronIO;
+using System.Text.RegularExpressions;
+using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
+
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
-using System.Text.RegularExpressions;
+using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
diff --git a/Essentials/PepperDashEssentials/ControlSystem.cs b/Essentials/PepperDashEssentials/ControlSystem.cs
index 16451812..9e995b5e 100644
--- a/Essentials/PepperDashEssentials/ControlSystem.cs
+++ b/Essentials/PepperDashEssentials/ControlSystem.cs
@@ -59,12 +59,12 @@ namespace PepperDash.Essentials
// CODEC TESTING
- GenericSshClient TestCodecClient = new GenericSshClient("TestCodec-1--SshClient", "10.11.50.135", 22, "crestron", "2H3Zu&OvgXp6");
+ //GenericSshClient TestCodecClient = new GenericSshClient("TestCodec-1--SshClient", "10.11.50.135", 22, "crestron", "2H3Zu&OvgXp6");
- PepperDash.Essentials.Devices.VideoCodec.Cisco.CiscoCodec TestCodec =
- new PepperDash.Essentials.Devices.VideoCodec.Cisco.CiscoCodec("TestCodec-1", "Cisco Spark Room Kit", TestCodecClient, 8080);
+ //PepperDash.Essentials.Devices.VideoCodec.Cisco.CiscoCodec TestCodec =
+ // new PepperDash.Essentials.Devices.VideoCodec.Cisco.CiscoCodec("TestCodec-1", "Cisco Spark Room Kit", TestCodecClient, 8080);
- TestCodec.CustomActivate();
+ //TestCodec.CustomActivate();
// CODEC TESTING
diff --git a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs b/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs
index 31cdc74a..f2568b8c 100644
--- a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs
+++ b/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs
@@ -41,10 +41,10 @@ namespace PepperDash.Essentials.Fusion
StringSigData CurrentRoomSourceNameSig;
#region System Info Sigs
- StringSigData SystemName;
- StringSigData Model;
- StringSigData SerialNumber;
- StringSigData Uptime;
+ //StringSigData SystemName;
+ //StringSigData Model;
+ //StringSigData SerialNumber;
+ //StringSigData Uptime;
#endregion
diff --git a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs.orig b/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs.orig
index b90a99d5..f783b3c7 100644
--- a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs.orig
+++ b/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs.orig
@@ -25,9 +25,9 @@ namespace PepperDash.Essentials.Fusion
{
public class EssentialsHuddleSpaceFusionSystemController : Device
{
- //public event EventHandler ScheduleChange;
- //public event EventHandler MeetingEndWarning;
- //public event EventHandler NextMeetingBeginWarning;
+ public event EventHandler ScheduleChange;
+ public event EventHandler MeetingEndWarning;
+ public event EventHandler NextMeetingBeginWarning;
FusionRoom FusionRoom;
EssentialsHuddleSpaceRoom Room;
@@ -41,10 +41,10 @@ namespace PepperDash.Essentials.Fusion
StringSigData CurrentRoomSourceNameSig;
#region System Info Sigs
- StringSigData SystemName;
- StringSigData Model;
- StringSigData SerialNumber;
- StringSigData Uptime;
+ //StringSigData SystemName;
+ //StringSigData Model;
+ //StringSigData SerialNumber;
+ //StringSigData Uptime;
#endregion
@@ -788,6 +788,15 @@ namespace PepperDash.Essentials.Fusion
if (!IsRegisteredForSchedulePushNotifications)
PollTimer.Reset(SchedulePollInterval, SchedulePollInterval);
+
+ // Fire Schedule Change Event
+ var handler = ScheduleChange;
+
+ if (handler != null)
+ {
+ handler(this, new ScheduleChangeEventArgs() { Schedule = CurrentSchedule });
+ }
+
}
}
@@ -806,20 +815,26 @@ namespace PepperDash.Essentials.Fusion
}
+ ///
+ /// Prints today's schedule to console for debugging
+ ///
void PrintTodaysSchedule()
{
- if (CurrentSchedule.Meetings.Count > 0)
+ if (Debug.Level > 1)
{
- Debug.Console(1, this, "Today's Schedule for '{0}'\n", Room.Name);
-
- foreach (Event e in CurrentSchedule.Meetings)
+ if (CurrentSchedule.Meetings.Count > 0)
{
- Debug.Console(1, this, "Subject: {0}", e.Subject);
- Debug.Console(1, this, "Organizer: {0}", e.Organizer);
- Debug.Console(1, this, "MeetingID: {0}", e.MeetingID);
- Debug.Console(1, this, "Start Time: {0}", e.dtStart);
- Debug.Console(1, this, "End Time: {0}", e.dtEnd);
- Debug.Console(1, this, "Duration: {0}\n", e.DurationInMinutes);
+ Debug.Console(1, this, "Today's Schedule for '{0}'\n", Room.Name);
+
+ foreach (Event e in CurrentSchedule.Meetings)
+ {
+ Debug.Console(1, this, "Subject: {0}", e.Subject);
+ Debug.Console(1, this, "Organizer: {0}", e.Organizer);
+ Debug.Console(1, this, "MeetingID: {0}", e.MeetingID);
+ Debug.Console(1, this, "Start Time: {0}", e.dtStart);
+ Debug.Console(1, this, "End Time: {0}", e.dtEnd);
+ Debug.Console(1, this, "Duration: {0}\n", e.DurationInMinutes);
+ }
}
}
}
@@ -888,13 +903,8 @@ namespace PepperDash.Essentials.Fusion
///
///
void UsageTracker_DeviceUsageEnded(object sender, DeviceUsageEventArgs e)
-<<<<<<< HEAD
- {
- var device = sender as Device;
-=======
{
var deviceTracker = sender as UsageTracking;
->>>>>>> origin/feature/fusion-nyu
var configDevice = ConfigReader.ConfigObject.Devices.Where(d => d.Key.Equals(deviceTracker.Parent));
@@ -960,6 +970,7 @@ namespace PepperDash.Essentials.Fusion
string attrName = null;
uint attrNum = Convert.ToUInt32(keyNum);
+<<<<<<< HEAD
if (dev is BasicTriListWithSmartObject)
@@ -971,13 +982,32 @@ namespace PepperDash.Essentials.Fusion
}
// add xpanel here
- if (dev is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
+ //if (dev is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
+ //{
+ // if (attrNum > 10)
+ // continue;
+ // attrName = "Online - XPanel " + attrNum;
+ // attrNum += 160;
+ //}
+=======
+ if (dev is EssentialsTouchpanelController)
{
- if (attrNum > 10)
- continue;
- attrName = "Online - XPanel " + attrNum;
- attrNum += 160;
- }
+ if ((dev as EssentialsTouchpanelController).Panel is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button)
+ {
+ if (attrNum > 10)
+ continue;
+ attrName = "Online - Touch Panel " + attrNum;
+ attrNum += 150;
+ }
+ else if ((dev as EssentialsTouchpanelController).Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
+ {
+ if (attrNum > 10)
+ continue;
+ attrName = "Online - XPanel " + attrNum;
+ attrNum += 160;
+ }
+ }
+>>>>>>> origin/feature/cisco-spark
//else
if (dev is DisplayBase)
diff --git a/Essentials/PepperDashEssentials/PepperDashEssentials.csproj b/Essentials/PepperDashEssentials/PepperDashEssentials.csproj
index 4e062dea..cafe9b6b 100644
--- a/Essentials/PepperDashEssentials/PepperDashEssentials.csproj
+++ b/Essentials/PepperDashEssentials/PepperDashEssentials.csproj
@@ -141,6 +141,9 @@
+
+
+
@@ -151,37 +154,42 @@
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs b/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs
new file mode 100644
index 00000000..2044484d
--- /dev/null
+++ b/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+namespace PepperDash.Essentials.Room.Config
+{
+ ///
+ ///
+ ///
+ public class EssentialsHuddleRoomPropertiesConfig : EssentialsRoomPropertiesConfig
+ {
+ public string DefaultDisplayKey { get; set; }
+ public string DefaultAudioKey { get; set; }
+ public string SourceListKey { get; set; }
+ public string DefaultSourceItem { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs b/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
new file mode 100644
index 00000000..1d9051d5
--- /dev/null
+++ b/Essentials/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+namespace PepperDash.Essentials.Room.Config
+{
+
+ public class EssentialsHuddleVtc1PropertiesConfig : EssentialsRoomPropertiesConfig
+ {
+ public string DefaultDisplayKey { get; set; }
+ public string DefaultAudioKey { get; set; }
+ public string SourceListKey { get; set; }
+ public string DefaultSourceItem { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Room/Config/EssentialsPresentationPropertiesConfig.cs b/Essentials/PepperDashEssentials/Room/Config/EssentialsPresentationPropertiesConfig.cs
new file mode 100644
index 00000000..a40e0fdc
--- /dev/null
+++ b/Essentials/PepperDashEssentials/Room/Config/EssentialsPresentationPropertiesConfig.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+namespace PepperDash.Essentials.Room.Config
+{
+ ///
+ ///
+ ///
+ public class EssentialsPresentationRoomPropertiesConfig : EssentialsRoomPropertiesConfig
+ {
+ public string DefaultAudioBehavior { get; set; }
+ public string DefaultAudioKey { get; set; }
+ public string DefaultVideoBehavior { get; set; }
+ public List DisplayKeys { get; set; }
+ public string SourceListKey { get; set; }
+ public bool HasDsp { get; set; }
+
+ public EssentialsPresentationRoomPropertiesConfig()
+ {
+ DisplayKeys = new List();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Room/EssentialsRoomConfig.cs b/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs
similarity index 67%
rename from Essentials/PepperDashEssentials/Room/EssentialsRoomConfig.cs
rename to Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs
index 89525d9e..7761d367 100644
--- a/Essentials/PepperDashEssentials/Room/EssentialsRoomConfig.cs
+++ b/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs
@@ -2,16 +2,16 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using System.Text.RegularExpressions;
+
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
+using PepperDash.Essentials;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
-using PepperDash.Essentials.DM;
-namespace PepperDash.Essentials
+namespace PepperDash.Essentials.Room.Config
{
public class EssentialsRoomConfig : DeviceConfig
{
@@ -54,6 +54,20 @@ namespace PepperDash.Essentials
var presRoom = new EssentialsPresentationRoom(Key, Name, displaysDict, masterVolumeControlDev, props);
return presRoom;
}
+ else if (typeName == "huddlevtc1")
+ {
+ var props = JsonConvert.DeserializeObject
+ (this.Properties.ToString());
+ var disp = DeviceManager.GetDeviceForKey(props.DefaultDisplayKey) as IRoutingSinkWithSwitching;
+ var rm = new EssentialsHuddleVtc1Room(Key, Name, disp, disp, props);
+ rm.LogoUrl = props.Logo.GetUrl();
+ rm.SourceListKey = props.SourceListKey;
+ rm.DefaultSourceItem = props.DefaultSourceItem;
+ rm.DefaultVolume = (ushort)(props.Volumes.Master.Level * 65535 / 100);
+
+ return rm;
+ }
+
return null;
}
}
@@ -67,12 +81,50 @@ namespace PepperDash.Essentials
public string Description { get; set; }
public int ShutdownVacancySeconds { get; set; }
public int ShutdownPromptSeconds { get; set; }
+ public EssentialsHelpPropertiesConfig Help { get; set; }
+ public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
+ public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
public EssentialsRoomOccSensorConfig OccupancySensors { get; set; }
public EssentialsLogoPropertiesConfig Logo { get; set; }
public EssentialsRoomVolumesConfig Volumes { get; set; }
}
+ ///
+ /// Properties for the help text box
+ ///
+ public class EssentialsHelpPropertiesConfig
+ {
+ public string Message { get; set; }
+ public bool ShowCallButton { get; set; }
+ ///
+ /// Defaults to "Call Help Desk"
+ ///
+ public string CallButtonText { get; set; }
+ public EssentialsHelpPropertiesConfig()
+ {
+ CallButtonText = "Call Help Desk";
+ }
+ }
+
+ ///
+ ///
+ ///
+ public class EssentialsOneButtonMeetingPropertiesConfig
+ {
+ public bool Enable { get; set; }
+ }
+
+ public class EssentialsRoomAddressPropertiesConfig
+ {
+ public string PhoneNumber { get; set; }
+ public string SipAddress { get; set; }
+ }
+
+
+ ///
+ /// Properties for the room's logo on panels
+ ///
public class EssentialsLogoPropertiesConfig
{
public string Type { get; set; }
@@ -100,32 +152,4 @@ namespace PepperDash.Essentials
public List Types { get; set; }
}
- ///
- ///
- ///
- public class EssentialsHuddleRoomPropertiesConfig : EssentialsRoomPropertiesConfig
- {
- public string DefaultDisplayKey { get; set; }
- public string DefaultAudioKey { get; set; }
- public string SourceListKey { get; set; }
- public string DefaultSourceItem { get; set; }
- }
-
- ///
- ///
- ///
- public class EssentialsPresentationRoomPropertiesConfig : EssentialsRoomPropertiesConfig
- {
- public string DefaultAudioBehavior { get; set; }
- public string DefaultAudioKey { get; set; }
- public string DefaultVideoBehavior { get; set; }
- public List DisplayKeys { get; set; }
- public string SourceListKey { get; set; }
- public bool HasDsp { get; set; }
-
- public EssentialsPresentationRoomPropertiesConfig()
- {
- DisplayKeys = new List();
- }
- }
}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs b/Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
similarity index 97%
rename from Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs
rename to Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
index 455fcd9b..7685de18 100644
--- a/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs
+++ b/Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
@@ -1,419 +1,420 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-
-using PepperDash.Core;
-using PepperDash.Essentials.Core;
-
-namespace PepperDash.Essentials
-{
- public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
- {
- public event EventHandler CurrentVolumeDeviceChange;
- public event SourceInfoChangeHandler CurrentSingleSourceChange;
-
- protected override Func OnFeedbackFunc
- {
- get
- {
- return () =>
- {
- var disp = DefaultDisplay as DisplayBase;
- var val = CurrentSourceInfo != null
- && CurrentSourceInfo.Type == eSourceListItemType.Route
- && disp != null
- && disp.PowerIsOnFeedback.BoolValue;
- return val;
- };
- }
- }
- ///
- ///
- ///
- protected override Func IsWarmingFeedbackFunc
- {
- get
- {
- return () =>
- {
- var disp = DefaultDisplay as DisplayBase;
- if (disp != null)
- return disp.IsWarmingUpFeedback.BoolValue;
- else
- return false;
- };
- }
- }
- ///
- ///
- ///
- protected override Func IsCoolingFeedbackFunc
- {
- get
- {
- return () =>
- {
- var disp = DefaultDisplay as DisplayBase;
- if (disp != null)
- return disp.IsCoolingDownFeedback.BoolValue;
- else
- return false;
- };
- }
- }
-
- public EssentialsRoomPropertiesConfig Config { get; private set; }
-
- public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
- public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
- public IBasicVolumeControls DefaultVolumeControls { get; private set; }
-
- public bool ExcludeFromGlobalFunctions { get; set; }
-
- ///
- /// The config name of the source list
- ///
- public string SourceListKey { get; set; }
-
- public string DefaultSourceItem { get; set; }
-
- public ushort DefaultVolume { get; set; }
-
- ///
- /// If room is off, enables power on to last source. Default true
- ///
- public bool EnablePowerOnToLastSource { get; set; }
- string LastSourceKey;
-
- ///
- ///
- ///
- public IBasicVolumeControls CurrentVolumeControls
- {
- get { return _CurrentAudioDevice; }
- set
- {
- if (value == _CurrentAudioDevice) return;
-
- var oldDev = _CurrentAudioDevice;
- // derigister this room from the device, if it can
- if (oldDev is IInUseTracking)
- (oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
- var handler = CurrentVolumeDeviceChange;
- if (handler != null)
- CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
- _CurrentAudioDevice = value;
- if (handler != null)
- CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
- // register this room with new device, if it can
- if (_CurrentAudioDevice is IInUseTracking)
- (_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
- }
- }
- IBasicVolumeControls _CurrentAudioDevice;
-
- ///
- /// The SourceListItem last run - containing names and icons
- ///
- public SourceListItem CurrentSourceInfo
- {
- get { return _CurrentSourceInfo; }
- private set
- {
- if (value == _CurrentSourceInfo) return;
-
- var handler = CurrentSingleSourceChange;
- // remove from in-use tracker, if so equipped
- if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
- (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
-
- if (handler != null)
- handler(this, _CurrentSourceInfo, ChangeType.WillChange);
-
- _CurrentSourceInfo = value;
-
- // add to in-use tracking
- if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
- (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
- if (handler != null)
- handler(this, _CurrentSourceInfo, ChangeType.DidChange);
- }
- }
- SourceListItem _CurrentSourceInfo;
-
- public string CurrentSourceInfoKey { get; private set; }
-
- ///
- ///
- ///
- ///
- ///
- public EssentialsHuddleSpaceRoom(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
- IRoutingSinkNoSwitching defaultAudio, EssentialsRoomPropertiesConfig config)
- : base(key, name)
- {
- Config = config;
- DefaultDisplay = defaultDisplay;
- DefaultAudioDevice = defaultAudio;
- if (defaultAudio is IBasicVolumeControls)
- DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
- else if (defaultAudio is IHasVolumeDevice)
- DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
- CurrentVolumeControls = DefaultVolumeControls;
-
- var disp = DefaultDisplay as DisplayBase;
- if (disp != null)
- {
- // Link power, warming, cooling to display
- disp.PowerIsOnFeedback.OutputChange += (o, a) =>
- {
- if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
- {
- if (!disp.PowerIsOnFeedback.BoolValue)
- CurrentSourceInfo = null;
- OnFeedback.FireUpdate();
- }
- };
-
- disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
- {
- IsWarmingUpFeedback.FireUpdate();
- if (!IsWarmingUpFeedback.BoolValue)
- (DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
- };
- disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
- {
- IsCoolingDownFeedback.FireUpdate();
- if (IsCoolingDownFeedback.BoolValue)
- (DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
- };
- }
-
- SourceListKey = "default";
- EnablePowerOnToLastSource = true;
- }
-
-
- ///
- ///
- ///
- public override void Shutdown()
- {
- RunRouteAction("roomOff");
- }
-
- ///
- /// Routes the default source item, if any
- ///
- public void RunDefaultRoute()
- {
- if (DefaultSourceItem != null)
- RunRouteAction(DefaultSourceItem);
- }
-
- ///
- ///
- ///
- ///
- public void RunRouteAction(string routeKey)
- {
- RunRouteAction(routeKey, null);
- }
-
- ///
- /// Gets a source from config list SourceListKey and dynamically build and executes the
- /// route or commands
- ///
- ///
- public void RunRouteAction(string routeKey, Action successCallback)
- {
- // Run this on a separate thread
- new CTimer(o =>
- {
- Debug.Console(1, this, "Run route action '{0}'", routeKey);
- var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
- if(dict == null)
- {
- Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
- return;
- }
-
- // Try to get the list item by it's string key
- if (!dict.ContainsKey(routeKey))
- {
- Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
- routeKey, SourceListKey);
- return;
- }
-
- var item = dict[routeKey];
- //Debug.Console(2, this, "Action {0} has {1} steps",
- // item.SourceKey, item.RouteList.Count);
-
- // End usage timer on last source
- if (!string.IsNullOrEmpty(LastSourceKey))
- {
- var lastSource = dict[LastSourceKey].SourceDevice;
-
- try
- {
- if (lastSource != null && lastSource is IUsageTracking)
- (lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
- }
- }
-
- // Let's run it
- if (routeKey.ToLower() != "roomoff")
- {
- LastSourceKey = routeKey;
- }
- else
- {
- CurrentSourceInfoKey = null;
- }
-
- foreach (var route in item.RouteList)
- {
- // if there is a $defaultAll on route, run two separate
- if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
- {
- // Going to assume a single-path route for now
- var tempVideo = new SourceRouteListItem
- {
- DestinationKey = "$defaultDisplay",
- SourceKey = route.SourceKey,
- Type = eRoutingSignalType.Video
- };
- DoRoute(tempVideo);
-
- //var tempAudio = new SourceRouteListItem
- //{
- // DestinationKey = "$defaultAudio",
- // SourceKey = route.SourceKey,
- // Type = eRoutingSignalType.Audio
- //};
- //DoRoute(tempAudio);
- //continue; -- not sure why this was here
- }
- else
- DoRoute(route);
- }
-
- // Start usage timer on routed source
- if (item.SourceDevice is IUsageTracking)
- {
- (item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
- }
-
-
- // Set volume control on room, using default if non provided
- IBasicVolumeControls volDev = null;
- // Handle special cases for volume control
- if (string.IsNullOrEmpty(item.VolumeControlKey)
- || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
- volDev = DefaultVolumeControls;
- else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
- volDev = DefaultDisplay as IBasicVolumeControls;
- // Or a specific device, probably rarely used.
- else
- {
- var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
- if (dev is IBasicVolumeControls)
- volDev = dev as IBasicVolumeControls;
- else if (dev is IHasVolumeDevice)
- volDev = (dev as IHasVolumeDevice).VolumeDevice;
- }
- CurrentVolumeControls = volDev;
-
- // store the name and UI info for routes
- if (item.SourceKey == "$off")
- {
- CurrentSourceInfoKey = routeKey;
- CurrentSourceInfo = null;
- }
- else if (item.SourceKey != null)
- {
- CurrentSourceInfoKey = routeKey;
- CurrentSourceInfo = item;
- }
- // And finally, set the "control". This will trigger event
- //CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
-
- OnFeedback.FireUpdate();
-
- // report back when done
- if (successCallback != null)
- successCallback();
-
- }, 0); // end of CTimer
- }
-
- ///
- /// Will power the room on with the last-used source
- ///
- public void PowerOnToDefaultOrLastSource()
- {
- if (!EnablePowerOnToLastSource || LastSourceKey == null)
- return;
- RunRouteAction(LastSourceKey);
- }
-
- ///
- ///
- ///
- ///
- ///
- bool DoRoute(SourceRouteListItem route)
- {
- IRoutingSinkNoSwitching dest = null;
-
- if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
- dest = DefaultAudioDevice;
- else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
- dest = DefaultDisplay;
- else
- dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
-
- if (dest == null)
- {
- Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
- return false;
- }
-
- if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
- {
- dest.ReleaseRoute();
- if (dest is IPower)
- (dest as IPower).PowerOff();
- }
- else
- {
- var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
- if (source == null)
- {
- Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
- return false;
- }
- dest.ReleaseAndMakeRoute(source, route.Type);
- }
- return true;
- }
-
- ///
- /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
- ///
- public static void AllRoomsOff()
- {
- var allRooms = DeviceManager.AllDevices.Where(d =>
- d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
- foreach (var room in allRooms)
- (room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Room.Config;
+
+namespace PepperDash.Essentials
+{
+ public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
+ {
+ public event EventHandler CurrentVolumeDeviceChange;
+ public event SourceInfoChangeHandler CurrentSingleSourceChange;
+
+ protected override Func OnFeedbackFunc
+ {
+ get
+ {
+ return () =>
+ {
+ var disp = DefaultDisplay as DisplayBase;
+ var val = CurrentSourceInfo != null
+ && CurrentSourceInfo.Type == eSourceListItemType.Route
+ && disp != null
+ && disp.PowerIsOnFeedback.BoolValue;
+ return val;
+ };
+ }
+ }
+ ///
+ ///
+ ///
+ protected override Func IsWarmingFeedbackFunc
+ {
+ get
+ {
+ return () =>
+ {
+ var disp = DefaultDisplay as DisplayBase;
+ if (disp != null)
+ return disp.IsWarmingUpFeedback.BoolValue;
+ else
+ return false;
+ };
+ }
+ }
+ ///
+ ///
+ ///
+ protected override Func IsCoolingFeedbackFunc
+ {
+ get
+ {
+ return () =>
+ {
+ var disp = DefaultDisplay as DisplayBase;
+ if (disp != null)
+ return disp.IsCoolingDownFeedback.BoolValue;
+ else
+ return false;
+ };
+ }
+ }
+
+ public EssentialsRoomPropertiesConfig Config { get; private set; }
+
+ public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
+ public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
+ public IBasicVolumeControls DefaultVolumeControls { get; private set; }
+
+ public bool ExcludeFromGlobalFunctions { get; set; }
+
+ ///
+ /// The config name of the source list
+ ///
+ public string SourceListKey { get; set; }
+
+ public string DefaultSourceItem { get; set; }
+
+ public ushort DefaultVolume { get; set; }
+
+ ///
+ /// If room is off, enables power on to last source. Default true
+ ///
+ public bool EnablePowerOnToLastSource { get; set; }
+ string LastSourceKey;
+
+ ///
+ ///
+ ///
+ public IBasicVolumeControls CurrentVolumeControls
+ {
+ get { return _CurrentAudioDevice; }
+ set
+ {
+ if (value == _CurrentAudioDevice) return;
+
+ var oldDev = _CurrentAudioDevice;
+ // derigister this room from the device, if it can
+ if (oldDev is IInUseTracking)
+ (oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
+ var handler = CurrentVolumeDeviceChange;
+ if (handler != null)
+ CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
+ _CurrentAudioDevice = value;
+ if (handler != null)
+ CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
+ // register this room with new device, if it can
+ if (_CurrentAudioDevice is IInUseTracking)
+ (_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
+ }
+ }
+ IBasicVolumeControls _CurrentAudioDevice;
+
+ ///
+ /// The SourceListItem last run - containing names and icons
+ ///
+ public SourceListItem CurrentSourceInfo
+ {
+ get { return _CurrentSourceInfo; }
+ private set
+ {
+ if (value == _CurrentSourceInfo) return;
+
+ var handler = CurrentSingleSourceChange;
+ // remove from in-use tracker, if so equipped
+ if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
+ (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
+
+ if (handler != null)
+ handler(this, _CurrentSourceInfo, ChangeType.WillChange);
+
+ _CurrentSourceInfo = value;
+
+ // add to in-use tracking
+ if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
+ (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
+ if (handler != null)
+ handler(this, _CurrentSourceInfo, ChangeType.DidChange);
+ }
+ }
+ SourceListItem _CurrentSourceInfo;
+
+ public string CurrentSourceInfoKey { get; private set; }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public EssentialsHuddleSpaceRoom(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
+ IRoutingSinkNoSwitching defaultAudio, EssentialsRoomPropertiesConfig config)
+ : base(key, name)
+ {
+ Config = config;
+ DefaultDisplay = defaultDisplay;
+ DefaultAudioDevice = defaultAudio;
+ if (defaultAudio is IBasicVolumeControls)
+ DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
+ else if (defaultAudio is IHasVolumeDevice)
+ DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
+ CurrentVolumeControls = DefaultVolumeControls;
+
+ var disp = DefaultDisplay as DisplayBase;
+ if (disp != null)
+ {
+ // Link power, warming, cooling to display
+ disp.PowerIsOnFeedback.OutputChange += (o, a) =>
+ {
+ if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
+ {
+ if (!disp.PowerIsOnFeedback.BoolValue)
+ CurrentSourceInfo = null;
+ OnFeedback.FireUpdate();
+ }
+ };
+
+ disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
+ {
+ IsWarmingUpFeedback.FireUpdate();
+ if (!IsWarmingUpFeedback.BoolValue)
+ (DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
+ };
+ disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
+ {
+ IsCoolingDownFeedback.FireUpdate();
+ if (IsCoolingDownFeedback.BoolValue)
+ (DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
+ };
+ }
+
+ SourceListKey = "default";
+ EnablePowerOnToLastSource = true;
+ }
+
+
+ ///
+ ///
+ ///
+ public override void Shutdown()
+ {
+ RunRouteAction("roomOff");
+ }
+
+ ///
+ /// Routes the default source item, if any
+ ///
+ public void RunDefaultRoute()
+ {
+ if (DefaultSourceItem != null)
+ RunRouteAction(DefaultSourceItem);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void RunRouteAction(string routeKey)
+ {
+ RunRouteAction(routeKey, null);
+ }
+
+ ///
+ /// Gets a source from config list SourceListKey and dynamically build and executes the
+ /// route or commands
+ ///
+ ///
+ public void RunRouteAction(string routeKey, Action successCallback)
+ {
+ // Run this on a separate thread
+ new CTimer(o =>
+ {
+ Debug.Console(1, this, "Run route action '{0}'", routeKey);
+ var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
+ if(dict == null)
+ {
+ Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
+ return;
+ }
+
+ // Try to get the list item by it's string key
+ if (!dict.ContainsKey(routeKey))
+ {
+ Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
+ routeKey, SourceListKey);
+ return;
+ }
+
+ var item = dict[routeKey];
+ //Debug.Console(2, this, "Action {0} has {1} steps",
+ // item.SourceKey, item.RouteList.Count);
+
+ // End usage timer on last source
+ if (!string.IsNullOrEmpty(LastSourceKey))
+ {
+ var lastSource = dict[LastSourceKey].SourceDevice;
+
+ try
+ {
+ if (lastSource != null && lastSource is IUsageTracking)
+ (lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
+ }
+ }
+
+ // Let's run it
+ if (routeKey.ToLower() != "roomoff")
+ {
+ LastSourceKey = routeKey;
+ }
+ else
+ {
+ CurrentSourceInfoKey = null;
+ }
+
+ foreach (var route in item.RouteList)
+ {
+ // if there is a $defaultAll on route, run two separate
+ if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
+ {
+ // Going to assume a single-path route for now
+ var tempVideo = new SourceRouteListItem
+ {
+ DestinationKey = "$defaultDisplay",
+ SourceKey = route.SourceKey,
+ Type = eRoutingSignalType.Video
+ };
+ DoRoute(tempVideo);
+
+ //var tempAudio = new SourceRouteListItem
+ //{
+ // DestinationKey = "$defaultAudio",
+ // SourceKey = route.SourceKey,
+ // Type = eRoutingSignalType.Audio
+ //};
+ //DoRoute(tempAudio);
+ //continue; -- not sure why this was here
+ }
+ else
+ DoRoute(route);
+ }
+
+ // Start usage timer on routed source
+ if (item.SourceDevice is IUsageTracking)
+ {
+ (item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
+ }
+
+
+ // Set volume control on room, using default if non provided
+ IBasicVolumeControls volDev = null;
+ // Handle special cases for volume control
+ if (string.IsNullOrEmpty(item.VolumeControlKey)
+ || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
+ volDev = DefaultVolumeControls;
+ else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
+ volDev = DefaultDisplay as IBasicVolumeControls;
+ // Or a specific device, probably rarely used.
+ else
+ {
+ var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
+ if (dev is IBasicVolumeControls)
+ volDev = dev as IBasicVolumeControls;
+ else if (dev is IHasVolumeDevice)
+ volDev = (dev as IHasVolumeDevice).VolumeDevice;
+ }
+ CurrentVolumeControls = volDev;
+
+ // store the name and UI info for routes
+ if (item.SourceKey == "$off")
+ {
+ CurrentSourceInfoKey = routeKey;
+ CurrentSourceInfo = null;
+ }
+ else if (item.SourceKey != null)
+ {
+ CurrentSourceInfoKey = routeKey;
+ CurrentSourceInfo = item;
+ }
+ // And finally, set the "control". This will trigger event
+ //CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
+
+ OnFeedback.FireUpdate();
+
+ // report back when done
+ if (successCallback != null)
+ successCallback();
+
+ }, 0); // end of CTimer
+ }
+
+ ///
+ /// Will power the room on with the last-used source
+ ///
+ public void PowerOnToDefaultOrLastSource()
+ {
+ if (!EnablePowerOnToLastSource || LastSourceKey == null)
+ return;
+ RunRouteAction(LastSourceKey);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ bool DoRoute(SourceRouteListItem route)
+ {
+ IRoutingSinkNoSwitching dest = null;
+
+ if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
+ dest = DefaultAudioDevice;
+ else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
+ dest = DefaultDisplay;
+ else
+ dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
+
+ if (dest == null)
+ {
+ Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
+ return false;
+ }
+
+ if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
+ {
+ dest.ReleaseRoute();
+ if (dest is IPower)
+ (dest as IPower).PowerOff();
+ }
+ else
+ {
+ var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
+ if (source == null)
+ {
+ Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
+ return false;
+ }
+ dest.ReleaseAndMakeRoute(source, route.Type);
+ }
+ return true;
+ }
+
+ ///
+ /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
+ ///
+ public static void AllRoomsOff()
+ {
+ var allRooms = DeviceManager.AllDevices.Where(d =>
+ d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
+ foreach (var room in allRooms)
+ (room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
+ }
+ }
}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
new file mode 100644
index 00000000..60bed37e
--- /dev/null
+++ b/Essentials/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
@@ -0,0 +1,407 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Room.Config;
+
+namespace PepperDash.Essentials
+{
+ public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange
+ {
+ public event EventHandler CurrentVolumeDeviceChange;
+ public event SourceInfoChangeHandler CurrentSingleSourceChange;
+
+ protected override Func OnFeedbackFunc
+ {
+ get
+ {
+ return () =>
+ {
+ var disp = DefaultDisplay as DisplayBase;
+ var val = CurrentSourceInfo != null
+ && CurrentSourceInfo.Type == eSourceListItemType.Route
+ && disp != null
+ && disp.PowerIsOnFeedback.BoolValue;
+ return val;
+ };
+ }
+ }
+ ///
+ ///
+ ///
+ protected override Func IsWarmingFeedbackFunc
+ {
+ get
+ {
+ return () =>
+ {
+ var disp = DefaultDisplay as DisplayBase;
+ if (disp != null)
+ return disp.IsWarmingUpFeedback.BoolValue;
+ else
+ return false;
+ };
+ }
+ }
+ ///
+ ///
+ ///
+ protected override Func IsCoolingFeedbackFunc
+ {
+ get
+ {
+ return () =>
+ {
+ var disp = DefaultDisplay as DisplayBase;
+ if (disp != null)
+ return disp.IsCoolingDownFeedback.BoolValue;
+ else
+ return false;
+ };
+ }
+ }
+
+ public EssentialsHuddleVtc1PropertiesConfig Config { get; private set; }
+
+ public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
+ public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
+ public IBasicVolumeControls DefaultVolumeControls { get; private set; }
+
+ public bool ExcludeFromGlobalFunctions { get; set; }
+
+ ///
+ /// The config name of the source list
+ ///
+ public string SourceListKey { get; set; }
+
+ public string DefaultSourceItem { get; set; }
+
+ public ushort DefaultVolume { get; set; }
+
+ ///
+ /// If room is off, enables power on to last source. Default true
+ ///
+ public bool EnablePowerOnToLastSource { get; set; }
+ string LastSourceKey;
+
+ ///
+ ///
+ ///
+ public IBasicVolumeControls CurrentVolumeControls
+ {
+ get { return _CurrentAudioDevice; }
+ set
+ {
+ if (value == _CurrentAudioDevice) return;
+
+ var oldDev = _CurrentAudioDevice;
+ // derigister this room from the device, if it can
+ if (oldDev is IInUseTracking)
+ (oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
+ var handler = CurrentVolumeDeviceChange;
+ if (handler != null)
+ CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
+ _CurrentAudioDevice = value;
+ if (handler != null)
+ CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
+ // register this room with new device, if it can
+ if (_CurrentAudioDevice is IInUseTracking)
+ (_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
+ }
+ }
+ IBasicVolumeControls _CurrentAudioDevice;
+
+ ///
+ /// The SourceListItem last run - containing names and icons
+ ///
+ public SourceListItem CurrentSourceInfo
+ {
+ get { return _CurrentSourceInfo; }
+ private set
+ {
+ if (value == _CurrentSourceInfo) return;
+
+ var handler = CurrentSingleSourceChange;
+ // remove from in-use tracker, if so equipped
+ if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
+ (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
+
+ if (handler != null)
+ handler(this, _CurrentSourceInfo, ChangeType.WillChange);
+
+ _CurrentSourceInfo = value;
+
+ // add to in-use tracking
+ if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
+ (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
+ if (handler != null)
+ handler(this, _CurrentSourceInfo, ChangeType.DidChange);
+ }
+ }
+ SourceListItem _CurrentSourceInfo;
+
+ public string CurrentSourceInfoKey { get; private set; }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public EssentialsHuddleVtc1Room(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
+ IRoutingSinkNoSwitching defaultAudio, EssentialsHuddleVtc1PropertiesConfig config)
+ : base(key, name)
+ {
+ Config = config;
+ DefaultDisplay = defaultDisplay;
+ DefaultAudioDevice = defaultAudio;
+ if (defaultAudio is IBasicVolumeControls)
+ DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
+ else if (defaultAudio is IHasVolumeDevice)
+ DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
+ CurrentVolumeControls = DefaultVolumeControls;
+
+ var disp = DefaultDisplay as DisplayBase;
+ if (disp != null)
+ {
+ // Link power, warming, cooling to display
+ disp.PowerIsOnFeedback.OutputChange += (o, a) =>
+ {
+ if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
+ {
+ if (!disp.PowerIsOnFeedback.BoolValue)
+ CurrentSourceInfo = null;
+ OnFeedback.FireUpdate();
+ }
+ };
+
+ disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
+ {
+ IsWarmingUpFeedback.FireUpdate();
+ if (!IsWarmingUpFeedback.BoolValue)
+ (DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
+ };
+ disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
+ {
+ IsCoolingDownFeedback.FireUpdate();
+ if (IsCoolingDownFeedback.BoolValue)
+ (DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
+ };
+ }
+
+ SourceListKey = "default";
+ EnablePowerOnToLastSource = true;
+ }
+
+
+ ///
+ ///
+ ///
+ public override void Shutdown()
+ {
+ RunRouteAction("roomOff");
+ }
+
+ ///
+ /// Routes the default source item, if any
+ ///
+ public void RunDefaultRoute()
+ {
+ if (DefaultSourceItem != null)
+ RunRouteAction(DefaultSourceItem);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void RunRouteAction(string routeKey)
+ {
+ RunRouteAction(routeKey, null);
+ }
+
+ ///
+ /// Gets a source from config list SourceListKey and dynamically build and executes the
+ /// route or commands
+ ///
+ ///
+ public void RunRouteAction(string routeKey, Action successCallback)
+ {
+ // Run this on a separate thread
+ new CTimer(o =>
+ {
+ Debug.Console(1, this, "Run route action '{0}'", routeKey);
+ var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
+ if(dict == null)
+ {
+ Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
+ return;
+ }
+
+ // Try to get the list item by it's string key
+ if (!dict.ContainsKey(routeKey))
+ {
+ Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
+ routeKey, SourceListKey);
+ return;
+ }
+
+ var item = dict[routeKey];
+
+ // End usage timer on last source
+ if (!string.IsNullOrEmpty(LastSourceKey))
+ {
+ var lastSource = dict[LastSourceKey].SourceDevice;
+
+ try
+ {
+ if (lastSource != null && lastSource is IUsageTracking)
+ (lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
+ }
+ }
+
+ // Let's run it
+ if (routeKey.ToLower() != "roomoff")
+ {
+ LastSourceKey = routeKey;
+ }
+ else
+ {
+ CurrentSourceInfoKey = null;
+ }
+
+ foreach (var route in item.RouteList)
+ {
+ // if there is a $defaultAll on route, run two separate
+ if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
+ {
+ // Going to assume a single-path route for now
+ var tempVideo = new SourceRouteListItem
+ {
+ DestinationKey = "$defaultDisplay",
+ SourceKey = route.SourceKey,
+ Type = eRoutingSignalType.Video
+ };
+ DoRoute(tempVideo);
+ }
+ else
+ DoRoute(route);
+ }
+
+ // Start usage timer on routed source
+ if (item.SourceDevice is IUsageTracking)
+ {
+ (item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
+ }
+
+
+ // Set volume control on room, using default if non provided
+ IBasicVolumeControls volDev = null;
+ // Handle special cases for volume control
+ if (string.IsNullOrEmpty(item.VolumeControlKey)
+ || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
+ volDev = DefaultVolumeControls;
+ else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
+ volDev = DefaultDisplay as IBasicVolumeControls;
+ // Or a specific device, probably rarely used.
+ else
+ {
+ var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
+ if (dev is IBasicVolumeControls)
+ volDev = dev as IBasicVolumeControls;
+ else if (dev is IHasVolumeDevice)
+ volDev = (dev as IHasVolumeDevice).VolumeDevice;
+ }
+ CurrentVolumeControls = volDev;
+
+ // store the name and UI info for routes
+ if (item.SourceKey == "$off")
+ {
+ CurrentSourceInfoKey = routeKey;
+ CurrentSourceInfo = null;
+ }
+ else if (item.SourceKey != null)
+ {
+ CurrentSourceInfoKey = routeKey;
+ CurrentSourceInfo = item;
+ }
+
+ OnFeedback.FireUpdate();
+
+ // report back when done
+ if (successCallback != null)
+ successCallback();
+
+ }, 0); // end of CTimer
+ }
+
+ ///
+ /// Will power the room on with the last-used source
+ ///
+ public void PowerOnToDefaultOrLastSource()
+ {
+ if (!EnablePowerOnToLastSource || LastSourceKey == null)
+ return;
+ RunRouteAction(LastSourceKey);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ bool DoRoute(SourceRouteListItem route)
+ {
+ IRoutingSinkNoSwitching dest = null;
+
+ if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
+ dest = DefaultAudioDevice;
+ else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
+ dest = DefaultDisplay;
+ else
+ dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
+
+ if (dest == null)
+ {
+ Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
+ return false;
+ }
+
+ if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
+ {
+ dest.ReleaseRoute();
+ if (dest is IPower)
+ (dest as IPower).PowerOff();
+ }
+ else
+ {
+ var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
+ if (source == null)
+ {
+ Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
+ return false;
+ }
+ dest.ReleaseAndMakeRoute(source, route.Type);
+ }
+ return true;
+ }
+
+ ///
+ /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
+ ///
+ public static void AllRoomsOff()
+ {
+ var allRooms = DeviceManager.AllDevices.Where(d =>
+ d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
+ foreach (var room in allRooms)
+ (room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/Room/EssentialsPresentationRoom.cs b/Essentials/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs
similarity index 99%
rename from Essentials/PepperDashEssentials/Room/EssentialsPresentationRoom.cs
rename to Essentials/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs
index 698013be..4cc4d197 100644
--- a/Essentials/PepperDashEssentials/Room/EssentialsPresentationRoom.cs
+++ b/Essentials/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs
@@ -6,6 +6,7 @@ using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
diff --git a/Essentials/PepperDashEssentials/Room/EssentialsRoomBase.cs b/Essentials/PepperDashEssentials/Room/Types/EssentialsRoomBase.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/Room/EssentialsRoomBase.cs
rename to Essentials/PepperDashEssentials/Room/Types/EssentialsRoomBase.cs
diff --git a/Essentials/PepperDashEssentials/Room/UI/CrestronTouchpanelPropertiesConfig.cs b/Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/CrestronTouchpanelPropertiesConfig.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/Room/UI/CrestronTouchpanelPropertiesConfig.cs
rename to Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/CrestronTouchpanelPropertiesConfig.cs
diff --git a/Essentials/PepperDashEssentials/Room/UI/DualDisplaySourceSRLController.cs b/Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/DualDisplaySourceSRLController.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/Room/UI/DualDisplaySourceSRLController.cs
rename to Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/DualDisplaySourceSRLController.cs
diff --git a/Essentials/PepperDashEssentials/Room/UI/EssentialsTouchpanelController.cs b/Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/EssentialsTouchpanelController.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/Room/UI/EssentialsTouchpanelController.cs
rename to Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/EssentialsTouchpanelController.cs
diff --git a/Essentials/PepperDashEssentials/Room/UI/SubpageReferenceListActivityItem.cs b/Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/SubpageReferenceListActivityItem.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/Room/UI/SubpageReferenceListActivityItem.cs
rename to Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/SubpageReferenceListActivityItem.cs
diff --git a/Essentials/PepperDashEssentials/Room/UI/SubpageReferenceListSourceItem.cs b/Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/SubpageReferenceListSourceItem.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/Room/UI/SubpageReferenceListSourceItem.cs
rename to Essentials/PepperDashEssentials/UI - FILES ORPHANED-DELETE/SubpageReferenceListSourceItem.cs
diff --git a/Essentials/PepperDashEssentials/UI Drivers/UISmartObjectJoin.cs b/Essentials/PepperDashEssentials/UI Drivers/UISmartObjectJoin.cs
deleted file mode 100644
index cc2e83c9..00000000
--- a/Essentials/PepperDashEssentials/UI Drivers/UISmartObjectJoin.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace PepperDash.Essentials
-{
- public class UISmartObjectJoin
- {
- ///
- /// 3200 The staging, source-select list
- ///
- public const uint StagingListSRL = 3200;
- ///
- /// 15022 The main activity footer
- ///
- public const uint ActivityFooterSRL = 15022;
- }
-}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI/CrestronTouchpanelPropertiesConfig.cs b/Essentials/PepperDashEssentials/UI/CrestronTouchpanelPropertiesConfig.cs
new file mode 100644
index 00000000..a79ef0b9
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UI/CrestronTouchpanelPropertiesConfig.cs
@@ -0,0 +1,47 @@
+namespace PepperDash.Essentials
+{
+ public class CrestronTouchpanelPropertiesConfig
+ {
+ public string IpId { get; set; }
+ public string DefaultRoomKey { get; set; }
+ public string RoomListKey { get; set; }
+ public string SgdFile { get; set; }
+ public string ProjectName { get; set; }
+ public bool ShowVolumeGauge { get; set; }
+ public bool UsesSplashPage { get; set; }
+ public bool ShowDate { get; set; }
+ public bool ShowTime { get; set; }
+ public UiSetupPropertiesConfig Setup { get; set; }
+ public UiHeaderStyle HeaderStyle { get; set; }
+
+ ///
+ /// The count of sources that will trigger the "additional" arrows to show on the SRL.
+ /// Defaults to 5
+ ///
+ public int SourcesOverflowCount { get; set; }
+
+ public CrestronTouchpanelPropertiesConfig()
+ {
+ SourcesOverflowCount = 5;
+ HeaderStyle = UiHeaderStyle.Habanero;
+ }
+ }
+
+ ///
+ ///
+ ///
+ public class UiSetupPropertiesConfig
+ {
+ public bool IsVisible { get; set; }
+ }
+
+ ///
+ ///
+ ///
+ public enum UiHeaderStyle
+ {
+ Habanero = 0,
+ Verbose
+ }
+
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI/DualDisplaySourceSRLController.cs b/Essentials/PepperDashEssentials/UI/DualDisplaySourceSRLController.cs
new file mode 100644
index 00000000..c91d72f1
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UI/DualDisplaySourceSRLController.cs
@@ -0,0 +1,28 @@
+//using System;
+//using System.Collections.Generic;
+//using System.Linq;
+//using System.Text;
+//using Crestron.SimplSharp;
+//using Crestron.SimplSharpPro;
+//using Crestron.SimplSharpPro.DeviceSupport;
+//using Crestron.SimplSharpPro.UI;
+
+//using PepperDash.Essentials.Core;
+
+//namespace PepperDash.Essentials
+//{
+// public class DualDisplaySourceSRLController : SubpageReferenceList
+// {
+// public DualDisplaySourceSRLController(BasicTriListWithSmartObject triList,
+// uint smartObjectId, EssentialsPresentationRoom room)
+// : base(triList, smartObjectId, 3, 3, 3)
+// {
+// var srcList = room.s items.Values.ToList().OrderBy(s => s.Order);
+// foreach (var item in srcList)
+// {
+// GetBoolFeedbackSig(index, 1).UserObject = new Action(routeAction);
+
+// }
+// }
+// }
+//}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs
new file mode 100644
index 00000000..6398a2c5
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs
@@ -0,0 +1,253 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharp.CrestronIO;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Crestron.SimplSharpPro.UI;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.PageManagers;
+
+namespace PepperDash.Essentials
+{
+ public class EssentialsTouchpanelController : Device
+ {
+ public BasicTriListWithSmartObject Panel { get; private set; }
+
+ public PanelDriverBase PanelDriver { get; private set; }
+
+ CTimer BacklightTransitionedOnTimer;
+
+ public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw,
+ string projectName, string sgdPath)
+ : base(key, name)
+ {
+ Panel = tsw;
+ tsw.LoadSmartObjects(sgdPath);
+ tsw.SigChange += new Crestron.SimplSharpPro.DeviceSupport.SigEventHandler(Tsw_SigChange);
+ }
+
+ ///
+ /// Config constructor
+ ///
+ public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
+ : base(key, name)
+ {
+ AddPostActivationAction(() =>
+ {
+ Debug.Console(0, this, "Creating hardware...");
+ type = type.ToLower();
+ try
+ {
+ if (type == "crestronapp")
+ {
+ var app = new CrestronApp(id, Global.ControlSystem);
+ app.ParameterProjectName.Value = props.ProjectName;
+ Panel = app;
+ }
+ else if (type == "tsw550")
+ Panel = new Tsw550(id, Global.ControlSystem);
+ else if (type == "tsw552")
+ Panel = new Tsw552(id, Global.ControlSystem);
+ else if (type == "tsw560")
+ Panel = new Tsw560(id, Global.ControlSystem);
+ else if (type == "tsw750")
+ Panel = new Tsw750(id, Global.ControlSystem);
+ else if (type == "tsw752")
+ Panel = new Tsw752(id, Global.ControlSystem);
+ else if (type == "tsw760")
+ Panel = new Tsw760(id, Global.ControlSystem);
+ else if (type == "tsw1050")
+ Panel = new Tsw1050(id, Global.ControlSystem);
+ else if (type == "tsw1052")
+ Panel = new Tsw1052(id, Global.ControlSystem);
+ else if (type == "tsw1060")
+ Panel = new Tsw1060(id, Global.ControlSystem);
+ else
+ {
+ Debug.Console(0, this, "WARNING: Cannot create TSW controller with type '{0}'", type);
+ return;
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, this, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
+ return;
+ }
+
+ // Reserved sigs
+ if (Panel is TswFt5ButtonSystem)
+ {
+ var tsw = Panel as TswFt5ButtonSystem;
+ tsw.ExtenderSystemReservedSigs.Use();
+ tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange
+ += ExtenderSystemReservedSigs_DeviceExtenderSigChange;
+ }
+
+ new CTimer(o =>
+ {
+ var regSuccess = Panel.Register();
+ if (regSuccess != eDeviceRegistrationUnRegistrationResponse.Success)
+ Debug.Console(0, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", regSuccess);
+
+ // Give up cleanly if SGD is not present.
+ var sgdName = @"\NVRAM\Program" + InitialParametersClass.ApplicationNumber
+ + @"\sgd\" + props.SgdFile;
+ if (!File.Exists(sgdName))
+ {
+ Debug.Console(0, this, "WARNING: Smart object file '{0}' not present. Exiting TSW load", sgdName);
+ return;
+ }
+
+ Panel.LoadSmartObjects(sgdName);
+ Panel.SigChange += Tsw_SigChange;
+
+ var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, props);
+ // Then the AV driver
+
+ // spin up different room drivers depending on room type
+ var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
+ if (room is EssentialsHuddleSpaceRoom)
+ {
+ Debug.Console(0, this, "Adding huddle space driver");
+ var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
+ avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
+ avDriver.DefaultRoomKey = props.DefaultRoomKey;
+ mainDriver.AvDriver = avDriver;
+ LoadAndShowDriver(mainDriver); // This is a little convoluted.
+
+ if (Panel is TswFt5ButtonSystem)
+ {
+ var tsw = Panel as TswFt5ButtonSystem;
+ // Wire up hard keys
+ tsw.Power.UserObject = new Action(b => { if (!b) avDriver.PowerButtonPressed(); });
+ //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); });
+ tsw.Up.UserObject = new Action(avDriver.VolumeUpPress);
+ tsw.Down.UserObject = new Action(avDriver.VolumeDownPress);
+ tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
+ }
+ }
+ else if (room is EssentialsPresentationRoom)
+ {
+ Debug.Console(0, this, "Adding presentation room driver");
+ var avDriver = new EssentialsPresentationPanelAvFunctionsDriver(mainDriver, props);
+ avDriver.CurrentRoom = room as EssentialsPresentationRoom;
+ avDriver.DefaultRoomKey = props.DefaultRoomKey;
+ mainDriver.AvDriver = avDriver;
+ LoadAndShowDriver(mainDriver);
+
+ if (Panel is TswFt5ButtonSystem)
+ {
+ var tsw = Panel as TswFt5ButtonSystem;
+ // Wire up hard keys
+ tsw.Power.UserObject = new Action(b => { if (!b) avDriver.PowerButtonPressed(); });
+ //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); });
+ tsw.Up.UserObject = new Action(avDriver.VolumeUpPress);
+ tsw.Down.UserObject = new Action(avDriver.VolumeDownPress);
+ tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
+ }
+ }
+ else if (room is EssentialsHuddleVtc1Room)
+ {
+ Debug.Console(0, this, "Adding huddle space driver");
+ var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props);
+ avDriver.CurrentRoom = room as EssentialsHuddleVtc1Room;
+ avDriver.DefaultRoomKey = props.DefaultRoomKey;
+ mainDriver.AvDriver = avDriver;
+ LoadAndShowDriver(mainDriver); // This is a little convoluted.
+
+ if (Panel is TswFt5ButtonSystem)
+ {
+ var tsw = Panel as TswFt5ButtonSystem;
+ // Wire up hard keys
+ tsw.Power.UserObject = new Action(b => { if (!b) avDriver.PowerButtonPressed(); });
+ //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); });
+ tsw.Up.UserObject = new Action(avDriver.VolumeUpPress);
+ tsw.Down.UserObject = new Action(avDriver.VolumeDownPress);
+ tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
+ }
+ }
+ else
+ {
+ Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
+ }
+ }, 0);
+ });
+ }
+
+ public void LoadAndShowDriver(PanelDriverBase driver)
+ {
+ PanelDriver = driver;
+ driver.Show();
+ }
+
+ void HomePressed()
+ {
+ if (BacklightTransitionedOnTimer == null)
+ PanelDriver.BackButtonPressed();
+ }
+
+
+ void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
+ {
+ // If the sig is transitioning on, mark it in case it was home button that transitioned it
+ var blOnSig = (Panel as TswFt5ButtonSystem).ExtenderSystemReservedSigs.BacklightOnFeedback;
+ if (args.Sig == blOnSig && blOnSig.BoolValue)
+ {
+ BacklightTransitionedOnTimer = new CTimer(o =>
+ {
+ BacklightTransitionedOnTimer = null;
+ }, 200);
+ }
+ }
+
+ public void PulseBool(uint join)
+ {
+ var act = Panel.BooleanInput[join].UserObject as Action;
+ if (act != null)
+ {
+ act(true);
+ act(false);
+ }
+ }
+
+ public void SetBoolSig(uint join, bool value)
+ {
+ var act = Panel.BooleanInput[join].UserObject as Action;
+ if (act != null)
+ act(value);
+ }
+
+ public void SetIntSig(uint join, ushort value)
+ {
+ var act = Panel.BooleanInput[join].UserObject as Action;
+ if (act != null)
+ {
+ act(value);
+ }
+ }
+
+ void Tsw_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
+ {
+ if (Debug.Level == 2)
+ Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
+ var uo = args.Sig.UserObject;
+ if (uo is Action)
+ (uo as Action)(args.Sig.BoolValue);
+ else if (uo is Action)
+ (uo as Action)(args.Sig.UShortValue);
+ else if (uo is Action)
+ (uo as Action)(args.Sig.StringValue);
+ }
+
+ void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
+ {
+ var uo = args.Button.UserObject;
+ if(uo is Action)
+ (uo as Action)(args.Button.State == eButtonState.Pressed);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI Drivers/UIBoolJoin.cs b/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
similarity index 68%
rename from Essentials/PepperDashEssentials/UI Drivers/UIBoolJoin.cs
rename to Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
index 8ebaf2ed..b54e40f6 100644
--- a/Essentials/PepperDashEssentials/UI Drivers/UIBoolJoin.cs
+++ b/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
@@ -22,6 +22,143 @@ namespace PepperDash.Essentials
///
public const uint VolumeDownPress = 902;
+ //******************************************************
+ // Audio Conference
+ ///
+ /// 1001
+ ///
+ public const uint ACKeypadVisible = 1001;
+ ///
+ /// 1002
+ ///
+ public const uint ACStagingPopoverVisible = 1002;
+ ///
+ /// 1011
+ ///
+ public const uint ACSpeedDial1Press = 1011;
+ ///
+ /// 1012
+ ///
+ public const uint ACSpeedDial2Press = 1012;
+ ///
+ /// 1013
+ ///
+ public const uint ACSpeedDial3Press = 1013;
+ ///
+ /// 1014
+ ///
+ public const uint ACSpeedDial4Press = 1014;
+ ///
+ /// 1021
+ ///
+ public const uint ACSpeedDial1Visible = 1021;
+ ///
+ /// 1022
+ ///
+ public const uint ACSpeedDial2Visible = 1022;
+ ///
+ /// 1023
+ ///
+ public const uint ACSpeedDial3Visible = 1023;
+ ///
+ /// 1024
+ ///
+ public const uint ACSpeedDial4Visible = 1024;
+
+ //******************************************************
+ // Video Conference
+ ///
+ /// 1201
+ ///
+ public const uint VCKeypadVisible = 1201;
+ ///
+ /// 1202
+ ///
+ public const uint VCStagingInactivePopoverVisible = 1202;
+ ///
+ ///
+ ///
+ public const uint VCStagingActivePopoverVisible = 1203;
+ ///
+ /// 1205
+ ///
+ public const uint VCDirectoryVisible = 1205;
+ ///
+ /// 1206
+ ///
+ public const uint VCRecentsVisible = 1206;
+ ///
+ /// 1207
+ ///
+ public const uint VCCameraVisible = 1207;
+ ///
+ /// 1211
+ ///
+ public const uint VCSpeedDial1Press = 1211;
+ ///
+ /// 1212
+ ///
+ public const uint VCSpeedDial2Press = 1212;
+ ///
+ /// 1213
+ ///
+ public const uint VCSpeedDial3Press = 1213;
+ ///
+ /// 1214
+ ///
+ public const uint VCSpeedDial4Press = 1214;
+ ///
+ /// 1221
+ ///
+ public const uint VCSpeedDial1Visible = 1221;
+ ///
+ /// 1222
+ ///
+ public const uint VCSpeedDial2Visible = 1222;
+ ///
+ /// 1223
+ ///
+ public const uint VCSpeedDial3Visible = 1223;
+ ///
+ /// 1224
+ ///
+ public const uint VCSpeedDial4Visible = 1224;
+ ///
+ /// 1231
+ ///
+ public const uint VCStagingRecentsPress = 1231;
+ ///
+ /// 1232
+ ///
+ public const uint VCStagingDirectoryPress = 1232;
+ ///
+ /// 1233
+ ///
+ public const uint VCStagingKeypadPress = 1233;
+ ///
+ /// 1234
+ ///
+ public const uint VCStagingConnectPress = 1234;
+ ///
+ /// 1235
+ ///
+ public const uint VCStagingCameraPress = 1235;
+
+ //******************************************************
+ // Keyboard
+ ///
+ /// 2901
+ ///
+ public const uint KeyboardVisible = 2901;
+ ///
+ /// 2910
+ ///
+ public const uint KeyboardClearPress = 2910;
+ ///
+ /// 2911
+ ///
+ public const uint KeyboardClearVisible = 2911;
+
///
/// 3811
///
@@ -34,19 +171,6 @@ namespace PepperDash.Essentials
/// 3813
///
public const uint Volume1ProgramMutePressAndFB = 3813;
- ///
- /// 3871
- ///
- public const uint VolumeDualMute1Visible = 3871;
- ///
- /// 3874
- ///
- public const uint Volume1SpeechMutePressAndFB = 3874;
- ///
- /// 3875
- ///
- public const uint Volume1BackerVisibility = 3875;
-
///
/// 3821
///
@@ -113,6 +237,22 @@ namespace PepperDash.Essentials
///
public const uint VolumesPageVisible = 3870;
///
+ /// 3871
+ ///
+ public const uint VolumeDualMute1Visible = 3871;
+ ///
+ /// 3874
+ ///
+ public const uint Volume1SpeechMutePressAndFB = 3874;
+ ///
+ /// 3875
+ ///
+ public const uint Volume1BackerVisibility = 3875;
+ ///
+ /// 3891
+ ///
+ public const uint VolumeDefaultPress = 3891;
+ ///
/// 3901
///
public const uint TechPagesExitButton = 3901;
@@ -157,13 +297,13 @@ namespace PepperDash.Essentials
///
public const uint ShowPanelSetupPress = 15010;
///
- /// 15011
+ /// 15011 - Top bar with room name and button that pops up dialog with room data
///
- public const uint TopBarVisible = 15011;
+ public const uint TopBarHabaneroVisible = 15011;
///
/// 15012
///
- public const uint StagingPageVisible = 15012;
+ public const uint SourceStagingBarVisible = 15012;
///
/// 15013
///
@@ -212,7 +352,7 @@ namespace PepperDash.Essentials
/// 15026
///
public const uint LightsHeaderButtonPress = 15026;
- ///
+ /// [-
/// 15027
///
public const uint CallHeaderButtonPress = 15027;
@@ -261,6 +401,14 @@ namespace PepperDash.Essentials
///
public const uint GearButtonVisible = 15037;
///
+ /// 15038
+ ///
+ public const uint CalendarHeaderButtonVisible = 15038;
+ ///
+ /// 15039
+ ///
+ public const uint CalendarHeaderButtonPress = 15039;
+ ///
/// 15040
///
public const uint CallStatusPageVisible = 15040;
@@ -280,8 +428,10 @@ namespace PepperDash.Essentials
/// 15044 Close button for source modal overlay
///
public const uint SourceBackgroundOverlayClosePress = 15044;
-
-
+ ///
+ /// 15045 - Visibility for the bar containing call navigation button list
+ ///
+ public const uint CallStagingBarVisible = 15045;
///
/// 15051
///
@@ -347,17 +497,22 @@ namespace PepperDash.Essentials
/// 15065
///
public const uint LogoUrlVisible = 15065;
-
+ ///
+ /// 15083 - Press for Call help desk on AC/VC
+ ///
+ public const uint HelpPageShowCallButtonPress = 15083;
+ ///
+ /// 15084 - Show the "call help desk" button on help page
+ ///
+ public const uint HelpPageShowCallButtonVisible = 15084;
///
/// 15085 Visibility join for help subpage
///
public const uint HelpPageVisible = 15085;
-
///
/// 15086 Press for help header button
///
public const uint HelpPress = 15086;
-
///
/// 15088
///
diff --git a/Essentials/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs b/Essentials/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs
new file mode 100644
index 00000000..3fdd58be
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs
@@ -0,0 +1,28 @@
+namespace PepperDash.Essentials
+{
+ public class UISmartObjectJoin
+ {
+ //******************************************************
+ // Video Conference
+
+ ///
+ /// 1201
+ ///
+ public const uint VCDialKeypad = 1201;
+
+ public const uint VCDirectoryList = 1202;
+
+ //******************************************************
+ // General
+
+ ///
+ /// 3200 The staging, source-select list
+ ///
+ public const uint SourceStagingSRL = 3200;
+ ///
+ /// 15022 The main activity footer
+ ///
+ public const uint ActivityFooterSRL = 15022;
+
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI Drivers/UIStringlJoin.cs b/Essentials/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs
similarity index 75%
rename from Essentials/PepperDashEssentials/UI Drivers/UIStringlJoin.cs
rename to Essentials/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs
index 28118f1e..bb709aad 100644
--- a/Essentials/PepperDashEssentials/UI Drivers/UIStringlJoin.cs
+++ b/Essentials/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs
@@ -9,10 +9,17 @@ using Crestron.SimplSharpPro.DeviceSupport;
namespace PepperDash.Essentials
{
///
- ///
+ /// Common string join number constants
///
public class UIStringJoin
{
+ //******************************************************
+ // Keyboard
+ ///
+ /// 1901
+ ///
+ public const uint KeyboardText = 2901;
+
///
/// 3812
///
@@ -51,6 +58,18 @@ namespace PepperDash.Essentials
///
public const uint CurrentSourceIcon = 3903;
///
+ /// 3904 - Phone number for room header
+ ///
+ public const uint RoomPhoneText = 3904;
+ ///
+ /// 3905 - SIP address for room header
+ ///
+ public const uint RoomSipText = 3905;
+ ///
+ /// 3906 - The separator for verbose-header text on addresses
+ ///
+ public const uint RoomAddressPipeText = 3906;
+ ///
/// 3911
///
public const uint PowerOffMessage = 3911;
@@ -71,11 +90,14 @@ namespace PepperDash.Essentials
/// 3922
///
public const uint HelpMessage = 3922;
-
///
/// 3923
///
public const uint LogoUrl = 3923;
+ ///
+ /// 3924 - the text on the "call help desk" button
+ ///
+ public const uint HelpPageCallButtonText = 3924;
///
/// 3961 Name of source on display 1
diff --git a/Essentials/PepperDashEssentials/UI Drivers/UIUshortJoin.cs b/Essentials/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/UI Drivers/UIUshortJoin.cs
rename to Essentials/PepperDashEssentials/UI/JoinConstants/UIUshortJoin.cs
diff --git a/Essentials/PepperDashEssentials/UI/SubpageReferenceListActivityItem.cs b/Essentials/PepperDashEssentials/UI/SubpageReferenceListActivityItem.cs
new file mode 100644
index 00000000..4747a61a
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UI/SubpageReferenceListActivityItem.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.UI;
+
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials
+{
+ public class SubpageReferenceListActivityItem : SubpageReferenceListItem
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 0=Share, 1=Phone Call, 2=Video Call, 3=End Meeting
+ ///
+ public SubpageReferenceListActivityItem(uint index, SubpageReferenceList owner,
+ ushort buttonMode, Action pressAction)
+ : base(index, owner)
+ {
+ Owner.GetBoolFeedbackSig(Index, 1).UserObject = pressAction;
+ Owner.UShortInputSig(Index, 1).UShortValue = buttonMode;
+ }
+
+ ///
+ /// Called by SRL to release all referenced objects
+ ///
+ public override void Clear()
+ {
+ Owner.BoolInputSig(Index, 1).UserObject = null;
+ Owner.UShortInputSig(Index, 1).UShortValue = 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI/SubpageReferenceListCallStagingItem.cs b/Essentials/PepperDashEssentials/UI/SubpageReferenceListCallStagingItem.cs
new file mode 100644
index 00000000..4c64bdd6
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UI/SubpageReferenceListCallStagingItem.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.UI;
+
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials
+{
+ public class SubpageReferenceListButtonAndModeItem : SubpageReferenceListItem
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 0=Share, 1=Phone Call, 2=Video Call, 3=End Meeting
+ ///
+ public SubpageReferenceListButtonAndModeItem(uint index, SubpageReferenceList owner,
+ ushort buttonMode, Action pressAction)
+ : base(index, owner)
+ {
+ Owner.GetBoolFeedbackSig(Index, 1).UserObject = pressAction;
+ Owner.UShortInputSig(Index, 1).UShortValue = buttonMode;
+ }
+
+ ///
+ /// Called by SRL to release all referenced objects
+ ///
+ public override void Clear()
+ {
+ Owner.BoolInputSig(Index, 1).UserObject = null;
+ Owner.UShortInputSig(Index, 1).UShortValue = 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI/SubpageReferenceListSourceItem.cs b/Essentials/PepperDashEssentials/UI/SubpageReferenceListSourceItem.cs
new file mode 100644
index 00000000..73cc5e71
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UI/SubpageReferenceListSourceItem.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.UI;
+
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials
+{
+ public class SubpageReferenceListSourceItem : SubpageReferenceListItem
+ {
+ public SourceListItem SourceItem { get; private set; }
+
+ public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner,
+ SourceListItem sourceItem, Action routeAction)
+ : base(index, owner)
+ {
+ SourceItem = sourceItem;
+ owner.GetBoolFeedbackSig(index, 1).UserObject = new Action(routeAction);
+ owner.StringInputSig(index, 1).StringValue = SourceItem.PreferredName;
+ }
+
+ public void RegisterForSourceChange(IHasCurrentSourceInfoChange room)
+ {
+ room.CurrentSingleSourceChange -= room_CurrentSourceInfoChange;
+ room.CurrentSingleSourceChange += room_CurrentSourceInfoChange;
+ }
+
+ void room_CurrentSourceInfoChange(EssentialsRoomBase room, SourceListItem info, ChangeType type)
+ {
+ if (type == ChangeType.WillChange && info == SourceItem)
+ ClearFeedback();
+ else if (type == ChangeType.DidChange && info == SourceItem)
+ SetFeedback();
+ }
+
+ ///
+ /// Called by SRL to release all referenced objects
+ ///
+ public override void Clear()
+ {
+ Owner.BoolInputSig(Index, 1).UserObject = null;
+ Owner.StringInputSig(Index, 1).StringValue = "";
+ }
+
+ ///
+ /// Sets the selected feedback on the button
+ ///
+ public void SetFeedback()
+ {
+ Owner.BoolInputSig(Index, 1).BoolValue = true;
+ }
+
+ ///
+ /// Clears the selected feedback on the button
+ ///
+ public void ClearFeedback()
+ {
+ Owner.BoolInputSig(Index, 1).BoolValue = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI Drivers/DualDisplayRouting.cs b/Essentials/PepperDashEssentials/UIDrivers/DualDisplayRouting.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/UI Drivers/DualDisplayRouting.cs
rename to Essentials/PepperDashEssentials/UIDrivers/DualDisplayRouting.cs
diff --git a/Essentials/PepperDashEssentials/UI Drivers/EssentialsHuddlePanelAvFunctionsDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/Essentials/EssentialsHuddlePanelAvFunctionsDriver.cs
similarity index 91%
rename from Essentials/PepperDashEssentials/UI Drivers/EssentialsHuddlePanelAvFunctionsDriver.cs
rename to Essentials/PepperDashEssentials/UIDrivers/Essentials/EssentialsHuddlePanelAvFunctionsDriver.cs
index 6c599488..dc5447d6 100644
--- a/Essentials/PepperDashEssentials/UI Drivers/EssentialsHuddlePanelAvFunctionsDriver.cs
+++ b/Essentials/PepperDashEssentials/UIDrivers/Essentials/EssentialsHuddlePanelAvFunctionsDriver.cs
@@ -1,970 +1,973 @@
-using System;
-using System.Collections.Generic;
-using Crestron.SimplSharp;
-using Crestron.SimplSharpPro;
-using Crestron.SimplSharpPro.UI;
-
-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;
-
- ///
- ///
- ///
- uint CurrentInterlockedModalJoin;
-
- ///
- /// 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
public override void Show()
{
- TriList.BooleanInput[UIBoolJoin.TopBarVisible].BoolValue = true;
+ TriList.BooleanInput[UIBoolJoin.TopBarHabaneroVisible].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.ActivityFooterVisible].BoolValue = true;
// Default to showing rooms/sources now.
@@ -266,12 +266,12 @@ namespace PepperDash.Essentials
{
var tl = TriList.BooleanInput;
HideAndClearCurrentDisplayModeSigsInUse();
- tl[UIBoolJoin.TopBarVisible].BoolValue = false;
+ tl[UIBoolJoin.TopBarHabaneroVisible].BoolValue = false;
tl[UIBoolJoin.ActivityFooterVisible].BoolValue = false;
tl[UIBoolJoin.StartPageVisible].BoolValue = false;
tl[UIBoolJoin.TapToBeginVisible].BoolValue = false;
tl[UIBoolJoin.ToggleSharingModeVisible].BoolValue = false;
- tl[UIBoolJoin.StagingPageVisible].BoolValue = false;
+ tl[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
if (IsSharingModeAdvanced)
tl[UIBoolJoin.DualDisplayPageVisible].BoolValue = false;
else
@@ -290,7 +290,7 @@ namespace PepperDash.Essentials
{
var tlb = TriList.BooleanInput;
tlb[UIBoolJoin.ToggleSharingModeVisible].BoolValue = true;
- tlb[UIBoolJoin.StagingPageVisible].BoolValue = true;
+ tlb[UIBoolJoin.SourceStagingBarVisible].BoolValue = true;
if (IsSharingModeAdvanced)
{
tlb[UIBoolJoin.DualDisplayPageVisible].BoolValue = true;
@@ -310,7 +310,7 @@ namespace PepperDash.Essentials
{
var tl = TriList.BooleanInput;
tl[UIBoolJoin.ToggleSharingModeVisible].BoolValue = false;
- tl[UIBoolJoin.StagingPageVisible].BoolValue = false;
+ tl[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
tl[UIBoolJoin.DualDisplayPageVisible].BoolValue = false;
tl[UIBoolJoin.SelectASourceVisible].BoolValue = false;
}
diff --git a/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/HuddleVTCPanelAvFunctionsDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/HuddleVTCPanelAvFunctionsDriver.cs
new file mode 100644
index 00000000..cb05d1b5
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/HuddleVTCPanelAvFunctionsDriver.cs
@@ -0,0 +1,940 @@
+using System;
+using System.Collections.Generic;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.UI;
+
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.SmartObjects;
+using PepperDash.Essentials.Core.PageManagers;
+using PepperDash.Essentials.Room.Config;
+
+namespace PepperDash.Essentials
+{
+ ///
+ ///
+ ///
+ public class EssentialsHuddleVtc1PanelAvFunctionsDriver : PanelDriverBase
+ {
+ CrestronTouchpanelPropertiesConfig Config;
+
+ public enum UiDisplayMode
+ {
+ Presentation, AudioSetup, Call, Start
+ }
+
+ ///
+ /// Whether volume ramping from this panel will show the volume
+ /// gauge popup.
+ ///
+ public bool ShowVolumeGauge { get; set; }
+
+ ///
+ ///
+ ///
+ public uint PowerOffTimeout { get; set; }
+
+ ///
+ ///
+ ///
+ public string DefaultRoomKey { get; set; }
+
+ ///
+ ///
+ ///
+ public EssentialsHuddleVtc1Room CurrentRoom
+ {
+ get { return _CurrentRoom; }
+ set
+ {
+ SetCurrentRoom(value);
+ }
+ }
+ EssentialsHuddleVtc1Room _CurrentRoom;
+
+ ///
+ /// For hitting feedback
+ ///
+ BoolInputSig CallButtonSig;
+ BoolInputSig ShareButtonSig;
+ BoolInputSig EndMeetingButtonSig;
+
+ ///
+ /// 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 SourceStagingSrl;
+
+ ///
+ /// 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;
+
+ ///
+ ///
+ ///
+ ModalDialog PowerDownModal;
+
+ ///
+ ///
+ ///
+ ModalDialog WarmingCoolingModal;
+
+ ///
+ /// Represents
+ ///
+ JoinedSigInterlock PopupInterlock;
+
+ ///
+ /// Interlock for various source, camera, call control bars. The bar above the activity footer. This is also
+ /// used to show start page
+ ///
+ JoinedSigInterlock StagingBarInterlock;
+
+ JoinedSigInterlock CallPagesInterlock;
+
+ PepperDash.Essentials.UIDrivers.VC.EssentialsCiscoSparkUiDriver VCDriver;
+
+ ///
+ /// Constructor
+ ///
+ public EssentialsHuddleVtc1PanelAvFunctionsDriver(PanelDriverBase parent, CrestronTouchpanelPropertiesConfig config)
+ : base(parent.TriList)
+ {
+ Config = config;
+ Parent = parent;
+
+ VCDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsCiscoSparkUiDriver(Parent.TriList, null);
+
+ PopupInterlock = new JoinedSigInterlock(TriList);
+ StagingBarInterlock = new JoinedSigInterlock(TriList);
+ CallPagesInterlock = new JoinedSigInterlock(TriList);
+
+ SourceStagingSrl = new SubpageReferenceList(TriList, UISmartObjectJoin.SourceStagingSRL, 3, 3, 3);
+
+ ActivityFooterSrl = new SubpageReferenceList(TriList, UISmartObjectJoin.ActivityFooterSRL, 3, 3, 3);
+ CallButtonSig = ActivityFooterSrl.BoolInputSig(1, 1);
+ ShareButtonSig = ActivityFooterSrl.BoolInputSig(2, 1);
+
+ SetupActivityFooterWhenRoomOff();
+
+ ShowVolumeGauge = true;
+ //PowerOffTimeout = 30000;
+
+ //TriList.StringInput[UIStringJoin.StartActivityText].StringValue = "Tap an activity below";
+ }
+
+ ///
+ ///
+ ///
+ public override void Show()
+ {
+ if (CurrentRoom == null)
+ {
+ Debug.Console(1, "ERROR: AVUIFunctionsDriver, Cannot show. No room assigned");
+ return;
+ }
+
+ var roomConf = CurrentRoom.Config;
+
+ if (Config.HeaderStyle == UiHeaderStyle.Habanero)
+ {
+ TriList.SetString(UIStringJoin.CurrentRoomName, CurrentRoom.Name);
+ TriList.SetSigFalseAction(UIBoolJoin.RoomHeaderButtonPress, () =>
+ PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.RoomHeaderPageVisible));
+ }
+ else if (Config.HeaderStyle == UiHeaderStyle.Verbose)
+ {
+ // room name on join 1, concat phone and sip on join 2, no button method
+ TriList.SetString(UIStringJoin.CurrentRoomName, CurrentRoom.Name);
+ var addr = roomConf.Addresses;
+ if (addr == null) // protect from missing values by using default empties
+ addr = new EssentialsRoomAddressPropertiesConfig();
+ // empty string when either missing, pipe when both showing
+ TriList.SetString(UIStringJoin.RoomAddressPipeText,
+ (string.IsNullOrEmpty(addr.PhoneNumber.Trim())
+ || string.IsNullOrEmpty(addr.SipAddress.Trim())) ? "" : " | ");
+ TriList.SetString(UIStringJoin.RoomPhoneText, addr.PhoneNumber);
+ TriList.SetString(UIStringJoin.RoomSipText, addr.SipAddress);
+ }
+
+ TriList.SetBool(UIBoolJoin.DateAndTimeVisible, Config.ShowDate && Config.ShowTime);
+ TriList.SetBool(UIBoolJoin.DateOnlyVisible, Config.ShowDate && !Config.ShowTime);
+ TriList.SetBool(UIBoolJoin.TimeOnlyVisible, !Config.ShowDate && Config.ShowTime);
+ TriList.SetBool(UIBoolJoin.TopBarHabaneroVisible, true);
+ TriList.SetBool(UIBoolJoin.ActivityFooterVisible, true);
+
+ // Default to showing rooms/sources now.
+ //ShowMode(UiDisplayMode.PresentationMode);
+ if (CurrentRoom.OnFeedback.BoolValue)
+ {
+ TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, true);
+ TriList.SetBool(UIBoolJoin.TapToBeginVisible, false);
+ TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
+ }
+ else
+ {
+ TriList.SetBool(UIBoolJoin.StartPageVisible, true);
+ TriList.SetBool(UIBoolJoin.TapToBeginVisible, true);
+ TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
+ }
+ ShowCurrentDisplayModeSigsInUse();
+
+ // *** Header Buttons ***
+
+ // Generic "close" button for these modals
+ TriList.SetSigFalseAction(UIBoolJoin.InterlockedModalClosePress, PopupInterlock.HideAndClear);
+
+ // Help button and popup
+ if (CurrentRoom.Config.Help != null)
+ {
+ TriList.SetString(UIStringJoin.HelpMessage, roomConf.Help.Message);
+ TriList.SetBool(UIBoolJoin.HelpPageShowCallButtonVisible, roomConf.Help.ShowCallButton);
+ TriList.SetString(UIStringJoin.HelpPageCallButtonText, roomConf.Help.CallButtonText);
+ if(roomConf.Help.ShowCallButton)
+ TriList.SetSigFalseAction(UIBoolJoin.HelpPageShowCallButtonPress, () => { }); // ************ FILL IN
+ else
+ TriList.ClearBoolSigAction(UIBoolJoin.HelpPageShowCallButtonPress);
+ }
+ else // older config
+ {
+ TriList.SetString(UIStringJoin.HelpMessage, CurrentRoom.Config.HelpMessage);
+ TriList.SetBool(UIBoolJoin.HelpPageShowCallButtonVisible, false);
+ TriList.SetString(UIStringJoin.HelpPageCallButtonText, null);
+ TriList.ClearBoolSigAction(UIBoolJoin.HelpPageShowCallButtonPress);
+ }
+ 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;
+ PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HelpPageVisible);
+ });
+
+ // Lights button
+ TriList.SetSigFalseAction(UIBoolJoin.LightsHeaderButtonPress, () => // ******************** FILL IN
+ { });
+
+ // Call header button
+ if(roomConf.OneButtonMeeting != null && roomConf.OneButtonMeeting.Enable)
+ {
+ TriList.SetBool(UIBoolJoin.CalendarHeaderButtonVisible, true);
+ TriList.SetSigFalseAction(UIBoolJoin.CallHeaderButtonPress, () =>
+ { });
+ }
+
+ // Setup button - shows volumes with default button OR hold for tech page
+ TriList.SetSigHeldAction(UIBoolJoin.GearHeaderButtonPress, 2000,
+ () => PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.TechPanelSetupVisible),
+ () => PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.VolumesPageVisible));
+ TriList.SetSigFalseAction(UIBoolJoin.TechPagesExitButton, () =>
+ PopupInterlock.HideAndClear());
+
+ // Default Volume button
+ TriList.SetSigFalseAction(UIBoolJoin.VolumeDefaultPress, () => // Set default volume method on room
+ { });
+
+
+ if (TriList is CrestronApp)
+ TriList.BooleanInput[UIBoolJoin.GearButtonVisible].BoolValue = false;
+ else
+ TriList.BooleanInput[UIBoolJoin.GearButtonVisible].BoolValue = true;
+
+ // 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.DisplayPowerTogglePress, () =>
+ {
+ if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IPower)
+ (CurrentRoom.DefaultDisplay as IPower).PowerToggle();
+ });
+
+ base.Show();
+ }
+
+ ///
+ /// Puts the UI into the "start" mode. System is off. Logo shows. Activity SRL is clear
+ ///
+ void ShowStartMode()
+ {
+ SetupActivityFooterWhenRoomOff();
+
+ ShareButtonSig.BoolValue = false;
+ CallButtonSig.BoolValue = false;
+ ShowLogo();
+ StagingBarInterlock.ShowInterlocked(UIBoolJoin.StartPageVisible);
+ StagingBarInterlock.HideAndClear();
+ }
+
+ void ShowShareMode()
+ {
+ ShareButtonSig.BoolValue = true;
+ CallButtonSig.BoolValue = false;
+ StagingBarInterlock.ShowInterlocked(UIBoolJoin.SourceStagingBarVisible);
+ }
+
+ void ShowVideoCallMode()
+ {
+ ShareButtonSig.BoolValue = false;
+ CallButtonSig.BoolValue = true;
+ StagingBarInterlock.ShowInterlocked(UIBoolJoin.CallStagingBarVisible);
+ }
+
+ ///
+ ///
+ ///
+ void ShowLogo()
+ {
+ if (CurrentRoom.LogoUrl == null)
+ {
+ TriList.SetBool(UIBoolJoin.LogoDefaultVisible, true);
+ TriList.SetBool(UIBoolJoin.LogoUrlVisible, false);
+ }
+ else
+ {
+ TriList.SetBool(UIBoolJoin.LogoDefaultVisible, false);
+ TriList.SetBool(UIBoolJoin.LogoUrlVisible, true);
+ TriList.SetString(UIStringJoin.LogoUrl, _CurrentRoom.LogoUrl);
+ }
+ }
+
+ ///
+ ///
+ ///
+ public override void Hide()
+ {
+ HideAndClearCurrentDisplayModeSigsInUse();
+ TriList.BooleanInput[UIBoolJoin.TopBarHabaneroVisible].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;
+ base.Hide();
+ }
+
+ ///
+ /// When the room is off, set the footer SRL
+ ///
+ void SetupActivityFooterWhenRoomOff()
+ {
+ ActivityFooterSrl.Clear();
+ ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl, 1,
+ b => { if (!b) ActivityCallButtonPressed(); }));
+ ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(2, ActivityFooterSrl, 0,
+ b => { if (!b) ActivityShareButtonPressed(); }));
+ ActivityFooterSrl.Count = 2;
+ TriList.UShortInput[UIUshortJoin.PresentationListCaretMode].UShortValue = 0;
+ ShareButtonSig.BoolValue = false;
+ }
+
+ ///
+ /// Sets up the footer SRL for when the room is on
+ ///
+ void SetupActivityFooterWhenRoomOn()
+ {
+ ActivityFooterSrl.Clear();
+ ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(1, ActivityFooterSrl, 1,
+ b => { if (!b) ActivityCallButtonPressed(); }));
+ ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(2, ActivityFooterSrl, 0,
+ b => { if (!b) ActivityShareButtonPressed(); }));
+ ActivityFooterSrl.AddItem(new SubpageReferenceListActivityItem(3, ActivityFooterSrl,
+ 3, b => { if (!b) PowerButtonPressed(); }));
+ ActivityFooterSrl.Count = 2;
+ TriList.UShortInput[UIUshortJoin.PresentationListCaretMode].UShortValue = 1;
+ EndMeetingButtonSig = ActivityFooterSrl.BoolInputSig(3, 1);
+
+ ShareButtonSig.BoolValue = CurrentRoom.OnFeedback.BoolValue;
+ }
+
+ ///
+ ///
+ ///
+ void ActivityCallButtonPressed()
+ {
+ if (VCDriver.IsVisible)
+ return;
+ CallButtonSig.BoolValue = true;
+ ShareButtonSig.BoolValue = false;
+ TriList.SetBool(UIBoolJoin.StartPageVisible, false);
+ TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false);
+ TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
+ VCDriver.Show();
+ }
+
+ ///
+ /// Attached to activity list share button
+ ///
+ void ActivityShareButtonPressed()
+ {
+ if (VCDriver.IsVisible)
+ VCDriver.Hide();
+ ShareButtonSig.BoolValue = true;
+ CallButtonSig.BoolValue = false;
+ TriList.SetBool(UIBoolJoin.StartPageVisible, false);
+ TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, true);
+ TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
+ // Run default source when room is off and share is pressed
+ if (!CurrentRoom.OnFeedback.BoolValue)
+ CurrentRoom.RunDefaultRoute();
+ }
+
+ ///
+ /// 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();
+ }
+
+
+ ///
+ /// 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 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
+ || CurrentRoom.ShutdownPromptTimer.IsRunningFeedback.BoolValue)
+ return;
+
+ CurrentRoom.StartShutdown(ShutdownType.Manual);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ void ShutdownPromptTimer_HasStarted(object sender, EventArgs e)
+ {
+ // Do we need to check where the UI is? No?
+ var timer = CurrentRoom.ShutdownPromptTimer;
+ EndMeetingButtonSig.BoolValue = true;
+ ShareButtonSig.BoolValue = false;
+
+ if (CurrentRoom.ShutdownType == ShutdownType.Manual)
+ {
+ PowerDownModal = new ModalDialog(TriList);
+ var message = string.Format("Meeting will end in {0} seconds", CurrentRoom.ShutdownPromptSeconds);
+
+ // Attach timer things to modal
+ CurrentRoom.ShutdownPromptTimer.TimeRemainingFeedback.OutputChange += ShutdownPromptTimer_TimeRemainingFeedback_OutputChange;
+ CurrentRoom.ShutdownPromptTimer.PercentFeedback.OutputChange += ShutdownPromptTimer_PercentFeedback_OutputChange;
+
+ // respond to offs by cancelling dialog
+ var onFb = CurrentRoom.OnFeedback;
+ EventHandler offHandler = null;
+ offHandler = (o, a) =>
+ {
+ if (!onFb.BoolValue)
+ {
+ EndMeetingButtonSig.BoolValue = false;
+ PowerDownModal.HideDialog();
+ onFb.OutputChange -= offHandler;
+ }
+ };
+ onFb.OutputChange += offHandler;
+
+ PowerDownModal.PresentModalDialog(2, "End Meeting", "Power", message, "Cancel", "End Meeting Now", true, true,
+ but =>
+ {
+ if (but != 2) // any button except for End cancels
+ timer.Cancel();
+ else
+ timer.Finish();
+ });
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ void ShutdownPromptTimer_HasFinished(object sender, EventArgs e)
+ {
+ //Debug.Console(2, "*#*UI shutdown prompt finished");
+ EndMeetingButtonSig.BoolValue = false;
+ CurrentRoom.ShutdownPromptTimer.TimeRemainingFeedback.OutputChange -= ShutdownPromptTimer_TimeRemainingFeedback_OutputChange;
+ CurrentRoom.ShutdownPromptTimer.PercentFeedback.OutputChange -= ShutdownPromptTimer_PercentFeedback_OutputChange;
+
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ void ShutdownPromptTimer_WasCancelled(object sender, EventArgs e)
+ {
+ //Debug.Console(2, "*#*UI shutdown prompt cancelled");
+ if (PowerDownModal != null)
+ PowerDownModal.HideDialog();
+ EndMeetingButtonSig.BoolValue = false;
+ ShareButtonSig.BoolValue = CurrentRoom.OnFeedback.BoolValue;
+
+ CurrentRoom.ShutdownPromptTimer.TimeRemainingFeedback.OutputChange += ShutdownPromptTimer_TimeRemainingFeedback_OutputChange;
+ CurrentRoom.ShutdownPromptTimer.PercentFeedback.OutputChange -= ShutdownPromptTimer_PercentFeedback_OutputChange;
+ }
+
+ void ShutdownPromptTimer_TimeRemainingFeedback_OutputChange(object sender, EventArgs e)
+ {
+
+ var message = string.Format("Meeting will end in {0} seconds", (sender as StringFeedback).StringValue);
+ TriList.StringInput[ModalDialog.MessageTextJoin].StringValue = message;
+ }
+
+ void ShutdownPromptTimer_PercentFeedback_OutputChange(object sender, EventArgs e)
+ {
+ var value = (ushort)((sender as IntFeedback).UShortValue * 65535 / 100);
+ TriList.UShortInput[ModalDialog.TimerGaugeJoin].UShortValue = value;
+ }
+
+ ///
+ ///
+ ///
+ void CancelPowerOffTimer()
+ {
+ if (PowerOffTimer != null)
+ {
+ PowerOffTimer.Stop();
+ PowerOffTimer = null;
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void VolumeUpPress(bool state)
+ {
+ if (CurrentRoom.CurrentVolumeControls != null)
+ CurrentRoom.CurrentVolumeControls.VolumeUp(state);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void VolumeDownPress(bool 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(EssentialsHuddleVtc1Room room)
+ {
+ if (_CurrentRoom == room) return;
+ // Disconnect current (probably never called)
+ if (_CurrentRoom != null)
+ {
+ // Disconnect current room
+ _CurrentRoom.CurrentVolumeDeviceChange -= this.CurrentRoom_CurrentAudioDeviceChange;
+ ClearAudioDeviceConnections();
+ _CurrentRoom.CurrentSingleSourceChange -= this.CurrentRoom_SourceInfoChange;
+ DisconnectSource(_CurrentRoom.CurrentSourceInfo);
+ _CurrentRoom.ShutdownPromptTimer.HasStarted -= ShutdownPromptTimer_HasStarted;
+ _CurrentRoom.ShutdownPromptTimer.HasFinished -= ShutdownPromptTimer_HasFinished;
+ _CurrentRoom.ShutdownPromptTimer.WasCancelled -= ShutdownPromptTimer_WasCancelled;
+
+ _CurrentRoom.OnFeedback.OutputChange += CurrentRoom_OnFeedback_OutputChange;
+ _CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange;
+ _CurrentRoom.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange;
+ }
+
+ _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(1, "Cannot assign missing source '{0}' to source UI list",
+ srcConfig.SourceKey);
+ continue;
+ }
+ var routeKey = kvp.Key;
+ var item = new SubpageReferenceListSourceItem(i++, SourceStagingSrl, srcConfig,
+ b => { if (!b) UiSelectSource(routeKey); });
+ SourceStagingSrl.AddItem(item); // add to the SRL
+ item.RegisterForSourceChange(_CurrentRoom);
+ }
+ SourceStagingSrl.Count = (ushort)(i - 1);
+ }
+ // Name and logo
+ TriList.StringInput[UIStringJoin.CurrentRoomName].StringValue = _CurrentRoom.Name;
+ ShowLogo();
+
+ // Shutdown timer
+ _CurrentRoom.ShutdownPromptTimer.HasStarted += ShutdownPromptTimer_HasStarted;
+ _CurrentRoom.ShutdownPromptTimer.HasFinished += ShutdownPromptTimer_HasFinished;
+ _CurrentRoom.ShutdownPromptTimer.WasCancelled += ShutdownPromptTimer_WasCancelled;
+
+ // Link up all the change events from the room
+ _CurrentRoom.OnFeedback.OutputChange += CurrentRoom_OnFeedback_OutputChange;
+ CurrentRoom_SyncOnFeedback();
+ _CurrentRoom.IsWarmingUpFeedback.OutputChange += CurrentRoom_IsWarmingFeedback_OutputChange;
+ _CurrentRoom.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_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)
+ {
+ CurrentRoom_SyncOnFeedback();
+ }
+
+ void CurrentRoom_SyncOnFeedback()
+ {
+ var value = _CurrentRoom.OnFeedback.BoolValue;
+ //Debug.Console(2, CurrentRoom, "UI: Is on event={0}", value);
+ TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value;
+
+ if (value) //ON
+ {
+ SetupActivityFooterWhenRoomOn();
+ TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
+ TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = true;
+ TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = false;
+ TriList.BooleanInput[UIBoolJoin.VolumeSingleMute1Visible].BoolValue = true;
+
+ }
+ else
+ {
+ SetupActivityFooterWhenRoomOff();
+ TriList.BooleanInput[UIBoolJoin.StartPageVisible].BoolValue = true;
+ TriList.BooleanInput[UIBoolJoin.VolumeSingleMute1Visible].BoolValue = false;
+ TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
+ }
+ }
+
+ ///
+ ///
+ ///
+ void CurrentRoom_IsWarmingFeedback_OutputChange(object sender, EventArgs e)
+ {
+ var value = CurrentRoom.IsWarmingUpFeedback.BoolValue;
+ //Debug.Console(2, CurrentRoom, "UI: WARMING event={0}", value);
+
+ if (value)
+ {
+ WarmingCoolingModal = new ModalDialog(TriList);
+ WarmingCoolingModal.PresentModalDialog(0, "Powering Up", "Power", "Room is powering up
Please wait
",
+ "", "", false, false, null);
+ }
+ else
+ {
+ if (WarmingCoolingModal != null)
+ WarmingCoolingModal.CancelDialog();
+ }
+ }
+
+
+ void IsCoolingDownFeedback_OutputChange(object sender, EventArgs e)
+ {
+ var value = CurrentRoom.IsCoolingDownFeedback.BoolValue;
+ //Debug.Console(2, CurrentRoom, "UI: Cooldown event={0}", value);
+
+ if (value)
+ {
+ WarmingCoolingModal = new ModalDialog(TriList);
+ WarmingCoolingModal.PresentModalDialog(0, "Shut Down", "Power", "Room is shutting down
Please wait
",
+ "", "", false, false, null);
+ }
+ else
+ {
+ if (WarmingCoolingModal != null)
+ WarmingCoolingModal.CancelDialog();
+ }
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// 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();
+ }
+ }
+}
diff --git a/Essentials/PepperDashEssentials/UIDrivers/JoinedSigInterlock.cs b/Essentials/PepperDashEssentials/UIDrivers/JoinedSigInterlock.cs
new file mode 100644
index 00000000..c383c7d3
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UIDrivers/JoinedSigInterlock.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro.DeviceSupport;
+
+namespace PepperDash.Essentials
+{
+ public class JoinedSigInterlock
+ {
+ public uint CurrentJoin { get; private set; }
+
+ BasicTriList TriList;
+
+ public JoinedSigInterlock(BasicTriList triList)
+ {
+ TriList = triList;
+ }
+
+ ///
+ /// Hides CurrentJoin and shows join. Does nothing when resending CurrentJoin
+ ///
+ public void ShowInterlocked(uint join)
+ {
+ if (CurrentJoin == join)
+ return;
+ SetButDontShow(join);
+ TriList.BooleanInput[CurrentJoin].BoolValue = true;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void ShowInterlockedWithToggle(uint join)
+ {
+ if (CurrentJoin == join)
+ HideAndClear();
+ else
+ {
+ if (CurrentJoin > 0)
+ TriList.BooleanInput[CurrentJoin].BoolValue = false;
+ CurrentJoin = join;
+ TriList.BooleanInput[CurrentJoin].BoolValue = true;
+ }
+ }
+ ///
+ /// Hides current join and clears CurrentJoin
+ ///
+ public void HideAndClear()
+ {
+ Hide();
+ CurrentJoin = 0;
+ }
+
+ ///
+ /// Hides the current join but does not clear the selected join in case
+ /// it needs to be reshown
+ ///
+ public void Hide()
+ {
+ if (CurrentJoin > 0)
+ TriList.BooleanInput[CurrentJoin].BoolValue = false;
+ }
+
+ ///
+ /// If CurrentJoin is set, it restores that join
+ ///
+ public void Show()
+ {
+ if (CurrentJoin > 0)
+ TriList.BooleanInput[CurrentJoin].BoolValue = true;
+ }
+
+ ///
+ /// Useful for pre-setting the interlock but not enabling it.
+ ///
+ ///
+ public void SetButDontShow(uint join)
+ {
+ if (CurrentJoin > 0)
+ TriList.BooleanInput[CurrentJoin].BoolValue = false;
+ CurrentJoin = join;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI Drivers/SingleSubpageModalAndBackDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/Page Drivers/SingleSubpageModalAndBackDriver.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/UI Drivers/SingleSubpageModalAndBackDriver.cs
rename to Essentials/PepperDashEssentials/UIDrivers/Page Drivers/SingleSubpageModalAndBackDriver.cs
diff --git a/Essentials/PepperDashEssentials/UI Drivers/SingleSubpageModalDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/Page Drivers/SingleSubpageModalDriver.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/UI Drivers/SingleSubpageModalDriver.cs
rename to Essentials/PepperDashEssentials/UIDrivers/Page Drivers/SingleSubpageModalDriver.cs
diff --git a/Essentials/PepperDashEssentials/UI Drivers/SmartObjectRoomsList.cs b/Essentials/PepperDashEssentials/UIDrivers/SmartObjectRoomsList.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/UI Drivers/SmartObjectRoomsList.cs
rename to Essentials/PepperDashEssentials/UIDrivers/SmartObjectRoomsList.cs
diff --git a/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsCiscoSparkUiDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsCiscoSparkUiDriver.cs
new file mode 100644
index 00000000..b61f39f6
--- /dev/null
+++ b/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsCiscoSparkUiDriver.cs
@@ -0,0 +1,235 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro.DeviceSupport;
+
+using PepperDash.Core;
+using PepperDash.Essentials;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.SmartObjects;
+using PepperDash.Essentials.Devices.Common.VideoCodec;
+
+namespace PepperDash.Essentials.UIDrivers.VC
+{
+
+ ///
+ /// This fella will likely need to interact with the room's source, although that is routed via the spark...
+ /// Probably needs event or FB to feed AV driver - to show two-mute volume when appropriate.
+ ///
+ ///
+ public class EssentialsCiscoSparkUiDriver : PanelDriverBase
+ {
+ VideoCodecBase Codec;
+
+ ///
+ ///
+ ///
+ SmartObjectDynamicList DirectorySrl; // ***************** SRL ???
+
+
+ ///
+ /// To drive UI elements outside of this driver that may be dependent on this.
+ ///
+ BoolFeedback InCall;
+ BoolFeedback LocalPrivacyIsMuted;
+
+ ///
+ /// For the subpages above the bar
+ ///
+ JoinedSigInterlock VCControlsInterlock;
+
+ ///
+ /// For the different staging bars: Active, inactive
+ ///
+ JoinedSigInterlock StagingBarInterlock;
+
+ ///
+ /// For the staging button feedbacks
+ ///
+ JoinedSigInterlock StagingButtonFeedbackInterlock;
+
+ SmartObjectNumeric DialKeypad;
+
+ // These are likely temp until we get a keyboard built
+ StringFeedback DialStringFeedback;
+ StringBuilder DialStringBuilder = new StringBuilder();
+ BoolFeedback DialStringBackspaceVisibleFeedback;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public EssentialsCiscoSparkUiDriver(BasicTriListWithSmartObject triList, VideoCodecBase codec)
+ : base(triList)
+ {
+ Codec = codec;
+ SetupCallStagingPopover();
+ SetupDialKeypad();
+
+ InCall = new BoolFeedback(() => false);
+ LocalPrivacyIsMuted = new BoolFeedback(() => false);
+
+ //DirectorySrl = new SubpageReferenceList(triList, UISmartObjectJoin.VCDirectoryList, 3, 3, 3);
+
+ VCControlsInterlock = new JoinedSigInterlock(triList);
+ VCControlsInterlock.SetButDontShow(UIBoolJoin.VCDirectoryVisible);
+
+ StagingBarInterlock = new JoinedSigInterlock(triList);
+ StagingBarInterlock.SetButDontShow(UIBoolJoin.VCStagingInactivePopoverVisible);
+
+ StagingButtonFeedbackInterlock = new JoinedSigInterlock(triList);
+ StagingButtonFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCRecentsVisible);
+
+ DialStringFeedback = new StringFeedback(() => DialStringBuilder.ToString());
+ DialStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.KeyboardText]);
+
+ DialStringBackspaceVisibleFeedback = new BoolFeedback(() => DialStringBuilder.Length > 0);
+ DialStringBackspaceVisibleFeedback
+ .LinkInputSig(TriList.BooleanInput[UIBoolJoin.KeyboardClearVisible]);
+
+ Codec.InCallFeedback.OutputChange += new EventHandler(InCallFeedback_OutputChange);
+ }
+
+ ///
+ ///
+ ///
+ public override void Show()
+ {
+ VCControlsInterlock.Show();
+ StagingBarInterlock.Show();
+ base.Show();
+ }
+
+ ///
+ ///
+ ///
+ public override void Hide()
+ {
+ VCControlsInterlock.Hide();
+ StagingBarInterlock.Hide();
+ base.Hide();
+ }
+
+ ///
+ /// Builds the call stage
+ ///
+ void SetupCallStagingPopover()
+ {
+ TriList.SetSigFalseAction(UIBoolJoin.VCStagingDirectoryPress, ShowDirectory);
+ TriList.SetSigFalseAction(UIBoolJoin.VCStagingConnectPress, ConnectPress);
+ TriList.SetSigFalseAction(UIBoolJoin.VCStagingKeypadPress, ShowKeypad);
+ TriList.SetSigFalseAction(UIBoolJoin.VCStagingRecentsPress, ShowRecents);
+ }
+
+ ///
+ ///
+ ///
+ void SetupDialKeypad()
+ {
+ if(TriList.SmartObjects.Contains(UISmartObjectJoin.VCDialKeypad))
+ {
+ DialKeypad = new SmartObjectNumeric(TriList.SmartObjects[UISmartObjectJoin.VCDialKeypad], true);
+ DialKeypad.Digit0.SetSigFalseAction(() => DialKeypadPress("0"));
+ DialKeypad.Digit1.SetSigFalseAction(() => DialKeypadPress("1"));
+ DialKeypad.Digit2.SetSigFalseAction(() => DialKeypadPress("2"));
+ DialKeypad.Digit3.SetSigFalseAction(() => DialKeypadPress("3"));
+ DialKeypad.Digit4.SetSigFalseAction(() => DialKeypadPress("4"));
+ DialKeypad.Digit5.SetSigFalseAction(() => DialKeypadPress("5"));
+ DialKeypad.Digit6.SetSigFalseAction(() => DialKeypadPress("6"));
+ DialKeypad.Digit7.SetSigFalseAction(() => DialKeypadPress("7"));
+ DialKeypad.Digit8.SetSigFalseAction(() => DialKeypadPress("8"));
+ DialKeypad.Digit9.SetSigFalseAction(() => DialKeypadPress("9"));
+ DialKeypad.Misc1SigName = "*";
+ DialKeypad.Misc1.SetSigFalseAction(() => DialKeypadPress("*"));
+ DialKeypad.Misc2SigName = "#";
+ DialKeypad.Misc2.SetSigFalseAction(() => DialKeypadPress("#"));
+ }
+ else
+ Debug.Console(0, "Trilist {0:x2}, VC dial keypad object {1} not found. Check SGD file or VTP",
+ TriList.ID, UISmartObjectJoin.VCDialKeypad);
+ }
+
+ ///
+ ///
+ ///
+ void ShowCameraControls()
+ {
+ VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCCameraVisible);
+ StagingButtonFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingCameraPress);
+ }
+
+ void ShowKeypad()
+ {
+ VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCKeypadVisible);
+ StagingButtonFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress);
+ }
+
+ void ShowDirectory()
+ {
+ // populate directory
+ VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCDirectoryVisible);
+ StagingButtonFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingDirectoryPress);
+ }
+
+ void ShowRecents()
+ {
+ //populate recents
+ VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCDirectoryVisible);
+ StagingButtonFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingRecentsPress);
+ }
+
+ ///
+ ///
+ ///
+ void ConnectPress()
+ {
+ if (Codec.InCallFeedback.BoolValue)
+ Codec.EndCall();
+ else
+ Codec.Dial(DialStringBuilder.ToString());
+ }
+
+ ///
+ ///
+ ///
+
+ void InCallFeedback_OutputChange(object sender, EventArgs e)
+ {
+ if (Codec.InCallFeedback.BoolValue) // Call is starting
+ {
+ // Header icon
+ // Add end call button to stage
+ // Volume bar needs to have mic mute
+ }
+ else // ending
+ {
+ // Header icon
+ // Remove end call
+ // Volume bar no mic mute (or hidden if no source?)
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ void DialKeypadPress(string i)
+ {
+ DialStringBuilder.Append(i);
+ DialStringFeedback.FireUpdate();
+ TriList.BooleanInput[UIBoolJoin.KeyboardClearVisible].BoolValue =
+ DialStringBuilder.Length > 0;
+ }
+
+ void DialKeypadBackspacePress()
+ {
+ DialStringBuilder.Remove(DialStringBuilder.Length - 1, 1);
+ DialStringFeedback.FireUpdate();
+ TriList.BooleanInput[UIBoolJoin.KeyboardClearVisible].BoolValue =
+ DialStringBuilder.Length > 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Essentials/PepperDashEssentials/UI Drivers/VolumeAndSourceChangeArgs.cs b/Essentials/PepperDashEssentials/UIDrivers/VolumeAndSourceChangeArgs.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/UI Drivers/VolumeAndSourceChangeArgs.cs
rename to Essentials/PepperDashEssentials/UIDrivers/VolumeAndSourceChangeArgs.cs
diff --git a/Essentials/PepperDashEssentials/UI Drivers/enums and base.cs b/Essentials/PepperDashEssentials/UIDrivers/enums and base.cs
similarity index 100%
rename from Essentials/PepperDashEssentials/UI Drivers/enums and base.cs
rename to Essentials/PepperDashEssentials/UIDrivers/enums and base.cs
diff --git a/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow.csproj b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow.csproj
new file mode 100644
index 00000000..33405f12
--- /dev/null
+++ b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow.csproj
@@ -0,0 +1,98 @@
+
+
+ Release
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {225C9CD0-1AA9-464C-A3A2-2117EE45A87E}
+ Library
+ Properties
+ EssentialsHuddleWorkflow
+ EssentialsHuddleWorkflow
+ {0B4745B0-194B-4BB6-8E21-E9057CA92300};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ WindowsCE
+ E2BECB1F-8C8C-41ba-B736-9BE7D946A398
+ 5.0
+ SmartDeviceProject1
+ v3.5
+ Windows CE
+
+
+
+
+ .allowedReferenceRelatedFileExtensions
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE;
+ prompt
+ 4
+ 512
+ true
+ true
+ off
+
+
+ .allowedReferenceRelatedFileExtensions
+ none
+ true
+ bin\Release\
+ prompt
+ 4
+ 512
+ true
+ true
+ off
+
+
+
+
+ False
+ ..\..\Essentials\PepperDashEssentials\bin\PepperDashEssentials.dll
+
+
+ False
+ ..\..\..\pepperdash-simplsharp-core\Pepperdash Core\CLZ Builds\PepperDash_Core.dll
+
+
+ False
+ ..\..\Essentials Core\PepperDashEssentialsBase\bin\PepperDash_Essentials_Core.dll
+
+
+ False
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll
+ False
+
+
+ False
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll
+ False
+
+
+ False
+ ..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rem S# Pro preparation will execute after these operations
+
+
\ No newline at end of file
diff --git a/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/Properties/AssemblyInfo.cs b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..0c28f7e6
--- /dev/null
+++ b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/Properties/AssemblyInfo.cs
@@ -0,0 +1,8 @@
+using System.Reflection;
+
+[assembly: AssemblyTitle("EssentialsHuddleWorkflow")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("EssentialsHuddleWorkflow")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyVersion("1.0.0.*")]
+
diff --git a/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/Properties/ControlSystem.cfg b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/Properties/ControlSystem.cfg
new file mode 100644
index 00000000..e69de29b
diff --git a/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/Room/EssentialsHuddleSpaceRoom.cs b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/Room/EssentialsHuddleSpaceRoom.cs
new file mode 100644
index 00000000..bc6749fe
--- /dev/null
+++ b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/Room/EssentialsHuddleSpaceRoom.cs
@@ -0,0 +1,420 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+using PepperDash.Core;
+using PepperDash.Essentials;
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials.EssentialsHuddleWorkflow
+{
+ public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
+ {
+ public event EventHandler CurrentVolumeDeviceChange;
+ public event SourceInfoChangeHandler CurrentSingleSourceChange;
+
+ protected override Func OnFeedbackFunc
+ {
+ get
+ {
+ return () =>
+ {
+ var disp = DefaultDisplay as DisplayBase;
+ var val = CurrentSourceInfo != null
+ && CurrentSourceInfo.Type == eSourceListItemType.Route
+ && disp != null
+ && disp.PowerIsOnFeedback.BoolValue;
+ return val;
+ };
+ }
+ }
+ ///
+ ///
+ ///
+ protected override Func IsWarmingFeedbackFunc
+ {
+ get
+ {
+ return () =>
+ {
+ var disp = DefaultDisplay as DisplayBase;
+ if (disp != null)
+ return disp.IsWarmingUpFeedback.BoolValue;
+ else
+ return false;
+ };
+ }
+ }
+ ///
+ ///
+ ///
+ protected override Func IsCoolingFeedbackFunc
+ {
+ get
+ {
+ return () =>
+ {
+ var disp = DefaultDisplay as DisplayBase;
+ if (disp != null)
+ return disp.IsCoolingDownFeedback.BoolValue;
+ else
+ return false;
+ };
+ }
+ }
+
+ public EssentialsRoomPropertiesConfig Config { get; private set; }
+
+ public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
+ public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
+ public IBasicVolumeControls DefaultVolumeControls { get; private set; }
+
+ public bool ExcludeFromGlobalFunctions { get; set; }
+
+ ///
+ /// The config name of the source list
+ ///
+ public string SourceListKey { get; set; }
+
+ public string DefaultSourceItem { get; set; }
+
+ public ushort DefaultVolume { get; set; }
+
+ ///
+ /// If room is off, enables power on to last source. Default true
+ ///
+ public bool EnablePowerOnToLastSource { get; set; }
+ string LastSourceKey;
+
+ ///
+ ///
+ ///
+ public IBasicVolumeControls CurrentVolumeControls
+ {
+ get { return _CurrentAudioDevice; }
+ set
+ {
+ if (value == _CurrentAudioDevice) return;
+
+ var oldDev = _CurrentAudioDevice;
+ // derigister this room from the device, if it can
+ if (oldDev is IInUseTracking)
+ (oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
+ var handler = CurrentVolumeDeviceChange;
+ if (handler != null)
+ CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
+ _CurrentAudioDevice = value;
+ if (handler != null)
+ CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
+ // register this room with new device, if it can
+ if (_CurrentAudioDevice is IInUseTracking)
+ (_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
+ }
+ }
+ IBasicVolumeControls _CurrentAudioDevice;
+
+ ///
+ /// The SourceListItem last run - containing names and icons
+ ///
+ public SourceListItem CurrentSourceInfo
+ {
+ get { return _CurrentSourceInfo; }
+ private set
+ {
+ if (value == _CurrentSourceInfo) return;
+
+ var handler = CurrentSingleSourceChange;
+ // remove from in-use tracker, if so equipped
+ if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
+ (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
+
+ if (handler != null)
+ handler(this, _CurrentSourceInfo, ChangeType.WillChange);
+
+ _CurrentSourceInfo = value;
+
+ // add to in-use tracking
+ if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
+ (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
+ if (handler != null)
+ handler(this, _CurrentSourceInfo, ChangeType.DidChange);
+ }
+ }
+ SourceListItem _CurrentSourceInfo;
+
+ public string CurrentSourceInfoKey { get; private set; }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public EssentialsHuddleSpaceRoom(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
+ IRoutingSinkNoSwitching defaultAudio, EssentialsRoomPropertiesConfig config)
+ : base(key, name)
+ {
+ Config = config;
+ DefaultDisplay = defaultDisplay;
+ DefaultAudioDevice = defaultAudio;
+ if (defaultAudio is IBasicVolumeControls)
+ DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
+ else if (defaultAudio is IHasVolumeDevice)
+ DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
+ CurrentVolumeControls = DefaultVolumeControls;
+
+ var disp = DefaultDisplay as DisplayBase;
+ if (disp != null)
+ {
+ // Link power, warming, cooling to display
+ disp.PowerIsOnFeedback.OutputChange += (o, a) =>
+ {
+ if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
+ {
+ if (!disp.PowerIsOnFeedback.BoolValue)
+ CurrentSourceInfo = null;
+ OnFeedback.FireUpdate();
+ }
+ };
+
+ disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
+ {
+ IsWarmingUpFeedback.FireUpdate();
+ if (!IsWarmingUpFeedback.BoolValue)
+ (DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
+ };
+ disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
+ {
+ IsCoolingDownFeedback.FireUpdate();
+ if (IsCoolingDownFeedback.BoolValue)
+ (DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
+ };
+ }
+
+ SourceListKey = "default";
+ EnablePowerOnToLastSource = true;
+ }
+
+
+ ///
+ ///
+ ///
+ public override void Shutdown()
+ {
+ RunRouteAction("roomOff");
+ }
+
+ ///
+ /// Routes the default source item, if any
+ ///
+ public void RunDefaultRoute()
+ {
+ if (DefaultSourceItem != null)
+ RunRouteAction(DefaultSourceItem);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void RunRouteAction(string routeKey)
+ {
+ RunRouteAction(routeKey, null);
+ }
+
+ ///
+ /// Gets a source from config list SourceListKey and dynamically build and executes the
+ /// route or commands
+ ///
+ ///
+ public void RunRouteAction(string routeKey, Action successCallback)
+ {
+ // Run this on a separate thread
+ new CTimer(o =>
+ {
+ Debug.Console(1, this, "Run route action '{0}'", routeKey);
+ var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
+ if(dict == null)
+ {
+ Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
+ return;
+ }
+
+ // Try to get the list item by it's string key
+ if (!dict.ContainsKey(routeKey))
+ {
+ Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
+ routeKey, SourceListKey);
+ return;
+ }
+
+ var item = dict[routeKey];
+ //Debug.Console(2, this, "Action {0} has {1} steps",
+ // item.SourceKey, item.RouteList.Count);
+
+ // End usage timer on last source
+ if (!string.IsNullOrEmpty(LastSourceKey))
+ {
+ var lastSource = dict[LastSourceKey].SourceDevice;
+
+ try
+ {
+ if (lastSource != null && lastSource is IUsageTracking)
+ (lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
+ }
+ }
+
+ // Let's run it
+ if (routeKey.ToLower() != "roomoff")
+ {
+ LastSourceKey = routeKey;
+ }
+ else
+ {
+ CurrentSourceInfoKey = null;
+ }
+
+ foreach (var route in item.RouteList)
+ {
+ // if there is a $defaultAll on route, run two separate
+ if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
+ {
+ // Going to assume a single-path route for now
+ var tempVideo = new SourceRouteListItem
+ {
+ DestinationKey = "$defaultDisplay",
+ SourceKey = route.SourceKey,
+ Type = eRoutingSignalType.Video
+ };
+ DoRoute(tempVideo);
+
+ //var tempAudio = new SourceRouteListItem
+ //{
+ // DestinationKey = "$defaultAudio",
+ // SourceKey = route.SourceKey,
+ // Type = eRoutingSignalType.Audio
+ //};
+ //DoRoute(tempAudio);
+ //continue; -- not sure why this was here
+ }
+ else
+ DoRoute(route);
+ }
+
+ // Start usage timer on routed source
+ if (item.SourceDevice is IUsageTracking)
+ {
+ (item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
+ }
+
+
+ // Set volume control on room, using default if non provided
+ IBasicVolumeControls volDev = null;
+ // Handle special cases for volume control
+ if (string.IsNullOrEmpty(item.VolumeControlKey)
+ || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
+ volDev = DefaultVolumeControls;
+ else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
+ volDev = DefaultDisplay as IBasicVolumeControls;
+ // Or a specific device, probably rarely used.
+ else
+ {
+ var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
+ if (dev is IBasicVolumeControls)
+ volDev = dev as IBasicVolumeControls;
+ else if (dev is IHasVolumeDevice)
+ volDev = (dev as IHasVolumeDevice).VolumeDevice;
+ }
+ CurrentVolumeControls = volDev;
+
+ // store the name and UI info for routes
+ if (item.SourceKey == "$off")
+ {
+ CurrentSourceInfoKey = routeKey;
+ CurrentSourceInfo = null;
+ }
+ else if (item.SourceKey != null)
+ {
+ CurrentSourceInfoKey = routeKey;
+ CurrentSourceInfo = item;
+ }
+ // And finally, set the "control". This will trigger event
+ //CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
+
+ OnFeedback.FireUpdate();
+
+ // report back when done
+ if (successCallback != null)
+ successCallback();
+
+ }, 0); // end of CTimer
+ }
+
+ ///
+ /// Will power the room on with the last-used source
+ ///
+ public void PowerOnToDefaultOrLastSource()
+ {
+ if (!EnablePowerOnToLastSource || LastSourceKey == null)
+ return;
+ RunRouteAction(LastSourceKey);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ bool DoRoute(SourceRouteListItem route)
+ {
+ IRoutingSinkNoSwitching dest = null;
+
+ if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
+ dest = DefaultAudioDevice;
+ else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
+ dest = DefaultDisplay;
+ else
+ dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
+
+ if (dest == null)
+ {
+ Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
+ return false;
+ }
+
+ if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
+ {
+ dest.ReleaseRoute();
+ if (dest is IPower)
+ (dest as IPower).PowerOff();
+ }
+ else
+ {
+ var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
+ if (source == null)
+ {
+ Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
+ return false;
+ }
+ dest.ReleaseAndMakeRoute(source, route.Type);
+ }
+ return true;
+ }
+
+ ///
+ /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
+ ///
+ public static void AllRoomsOff()
+ {
+ var allRooms = DeviceManager.AllDevices.Where(d =>
+ d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
+ foreach (var room in allRooms)
+ (room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
+ }
+ }
+}
\ No newline at end of file
diff --git a/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/DualDisplaySourceSRLController.cs b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/DualDisplaySourceSRLController.cs
new file mode 100644
index 00000000..c91d72f1
--- /dev/null
+++ b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/DualDisplaySourceSRLController.cs
@@ -0,0 +1,28 @@
+//using System;
+//using System.Collections.Generic;
+//using System.Linq;
+//using System.Text;
+//using Crestron.SimplSharp;
+//using Crestron.SimplSharpPro;
+//using Crestron.SimplSharpPro.DeviceSupport;
+//using Crestron.SimplSharpPro.UI;
+
+//using PepperDash.Essentials.Core;
+
+//namespace PepperDash.Essentials
+//{
+// public class DualDisplaySourceSRLController : SubpageReferenceList
+// {
+// public DualDisplaySourceSRLController(BasicTriListWithSmartObject triList,
+// uint smartObjectId, EssentialsPresentationRoom room)
+// : base(triList, smartObjectId, 3, 3, 3)
+// {
+// var srcList = room.s items.Values.ToList().OrderBy(s => s.Order);
+// foreach (var item in srcList)
+// {
+// GetBoolFeedbackSig(index, 1).UserObject = new Action(routeAction);
+
+// }
+// }
+// }
+//}
\ No newline at end of file
diff --git a/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/EssentialsTouchpanelController.cs b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/EssentialsTouchpanelController.cs
new file mode 100644
index 00000000..8ad6ab1a
--- /dev/null
+++ b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/EssentialsTouchpanelController.cs
@@ -0,0 +1,221 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharp.CrestronIO;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Crestron.SimplSharpPro.UI;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.PageManagers;
+
+namespace PepperDash.Essentials
+{
+ public class EssentialsTouchpanelController : Device
+ {
+ public BasicTriListWithSmartObject Panel { get; private set; }
+
+ public PanelDriverBase PanelDriver { get; private set; }
+
+ CTimer BacklightTransitionedOnTimer;
+
+ public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw,
+ string projectName, string sgdPath)
+ : base(key, name)
+ {
+ Panel = tsw;
+ tsw.LoadSmartObjects(sgdPath);
+ tsw.SigChange += new Crestron.SimplSharpPro.DeviceSupport.SigEventHandler(Tsw_SigChange);
+ }
+
+ ///
+ /// Config constructor
+ ///
+ public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
+ : base(key, name)
+ {
+ AddPostActivationAction(() =>
+ {
+ Debug.Console(0, this, "post-activation linking");
+ type = type.ToLower();
+ try
+ {
+ if (type == "crestronapp")
+ {
+ var app = new CrestronApp(id, Global.ControlSystem);
+ app.ParameterProjectName.Value = props.ProjectName;
+ Panel = app;
+ }
+ else if (type == "tsw560")
+ Panel = new Tsw560(id, Global.ControlSystem);
+ else if (type == "tsw752")
+ Panel = new Tsw752(id, Global.ControlSystem);
+ else if (type == "tsw1052")
+ Panel = new Tsw1052(id, Global.ControlSystem);
+ else
+ {
+ Debug.Console(0, this, "WARNING: Cannot create TSW controller with type '{0}'", type);
+ return;
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, this, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
+ return;
+ }
+
+ // Reserved sigs
+ if (Panel is TswFt5ButtonSystem)
+ {
+ var tsw = Panel as TswFt5ButtonSystem;
+ tsw.ExtenderSystemReservedSigs.Use();
+ tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange
+ += ExtenderSystemReservedSigs_DeviceExtenderSigChange;
+ }
+
+ new CTimer(o =>
+ {
+ var regSuccess = Panel.Register();
+ if (regSuccess != eDeviceRegistrationUnRegistrationResponse.Success)
+ Debug.Console(0, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", regSuccess);
+
+ // Give up cleanly if SGD is not present.
+ var sgdName = @"\NVRAM\Program" + InitialParametersClass.ApplicationNumber
+ + @"\sgd\" + props.SgdFile;
+ if (!File.Exists(sgdName))
+ {
+ Debug.Console(0, this, "WARNING: Smart object file '{0}' not present. Exiting TSW load", sgdName);
+ return;
+ }
+
+ Panel.LoadSmartObjects(sgdName);
+ Panel.SigChange += Tsw_SigChange;
+
+ var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, props);
+ // Then the AV driver
+
+ // spin up different room drivers depending on room type
+ var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
+ if (room is EssentialsHuddleSpaceRoom)
+ {
+ Debug.Console(0, this, "Adding huddle space driver");
+ var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
+ avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
+ avDriver.DefaultRoomKey = props.DefaultRoomKey;
+ mainDriver.AvDriver = avDriver;
+ LoadAndShowDriver(mainDriver); // This is a little convoluted.
+
+ if (Panel is TswFt5ButtonSystem)
+ {
+ var tsw = Panel as TswFt5ButtonSystem;
+ // Wire up hard keys
+ tsw.Power.UserObject = new Action(b => { if (!b) avDriver.PowerButtonPressed(); });
+ //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); });
+ tsw.Up.UserObject = new Action(avDriver.VolumeUpPress);
+ tsw.Down.UserObject = new Action(avDriver.VolumeDownPress);
+ tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
+ }
+ }
+ else if (room is EssentialsPresentationRoom)
+ {
+ Debug.Console(0, this, "Adding presentation room driver");
+ var avDriver = new EssentialsPresentationPanelAvFunctionsDriver(mainDriver, props);
+ avDriver.CurrentRoom = room as EssentialsPresentationRoom;
+ avDriver.DefaultRoomKey = props.DefaultRoomKey;
+ mainDriver.AvDriver = avDriver;
+ LoadAndShowDriver(mainDriver);
+
+ if (Panel is TswFt5ButtonSystem)
+ {
+ var tsw = Panel as TswFt5ButtonSystem;
+ // Wire up hard keys
+ tsw.Power.UserObject = new Action(b => { if (!b) avDriver.PowerButtonPressed(); });
+ //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); });
+ tsw.Up.UserObject = new Action(avDriver.VolumeUpPress);
+ tsw.Down.UserObject = new Action(avDriver.VolumeDownPress);
+ tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
+ }
+ }
+ else
+ {
+ Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
+ }
+ }, 0);
+ });
+ }
+
+ public void LoadAndShowDriver(PanelDriverBase driver)
+ {
+ PanelDriver = driver;
+ driver.Show();
+ }
+
+ void HomePressed()
+ {
+ if (BacklightTransitionedOnTimer == null)
+ PanelDriver.BackButtonPressed();
+ }
+
+
+ void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
+ {
+ // If the sig is transitioning on, mark it in case it was home button that transitioned it
+ var blOnSig = (Panel as TswFt5ButtonSystem).ExtenderSystemReservedSigs.BacklightOnFeedback;
+ if (args.Sig == blOnSig && blOnSig.BoolValue)
+ {
+ BacklightTransitionedOnTimer = new CTimer(o =>
+ {
+ BacklightTransitionedOnTimer = null;
+ }, 200);
+ }
+ }
+
+ public void PulseBool(uint join)
+ {
+ var act = Panel.BooleanInput[join].UserObject as Action;
+ if (act != null)
+ {
+ act(true);
+ act(false);
+ }
+ }
+
+ public void SetBoolSig(uint join, bool value)
+ {
+ var act = Panel.BooleanInput[join].UserObject as Action;
+ if (act != null)
+ act(value);
+ }
+
+ public void SetIntSig(uint join, ushort value)
+ {
+ var act = Panel.BooleanInput[join].UserObject as Action;
+ if (act != null)
+ {
+ act(value);
+ }
+ }
+
+ void Tsw_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
+ {
+ if (Debug.Level == 2)
+ Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
+ var uo = args.Sig.UserObject;
+ if (uo is Action)
+ (uo as Action)(args.Sig.BoolValue);
+ else if (uo is Action)
+ (uo as Action)(args.Sig.UShortValue);
+ else if (uo is Action)
+ (uo as Action)(args.Sig.StringValue);
+ }
+
+ void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
+ {
+ var uo = args.Button.UserObject;
+ if(uo is Action)
+ (uo as Action)(args.Button.State == eButtonState.Pressed);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/SubpageReferenceListActivityItem.cs b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/SubpageReferenceListActivityItem.cs
new file mode 100644
index 00000000..4747a61a
--- /dev/null
+++ b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/SubpageReferenceListActivityItem.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.UI;
+
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials
+{
+ public class SubpageReferenceListActivityItem : SubpageReferenceListItem
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 0=Share, 1=Phone Call, 2=Video Call, 3=End Meeting
+ ///
+ public SubpageReferenceListActivityItem(uint index, SubpageReferenceList owner,
+ ushort buttonMode, Action pressAction)
+ : base(index, owner)
+ {
+ Owner.GetBoolFeedbackSig(Index, 1).UserObject = pressAction;
+ Owner.UShortInputSig(Index, 1).UShortValue = buttonMode;
+ }
+
+ ///
+ /// Called by SRL to release all referenced objects
+ ///
+ public override void Clear()
+ {
+ Owner.BoolInputSig(Index, 1).UserObject = null;
+ Owner.UShortInputSig(Index, 1).UShortValue = 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/SubpageReferenceListSourceItem.cs b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/SubpageReferenceListSourceItem.cs
new file mode 100644
index 00000000..73cc5e71
--- /dev/null
+++ b/EssentialsHuddleWorkflow/EssentialsHuddleWorkflow/UI/SubpageReferenceListSourceItem.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.UI;
+
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials
+{
+ public class SubpageReferenceListSourceItem : SubpageReferenceListItem
+ {
+ public SourceListItem SourceItem { get; private set; }
+
+ public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner,
+ SourceListItem sourceItem, Action routeAction)
+ : base(index, owner)
+ {
+ SourceItem = sourceItem;
+ owner.GetBoolFeedbackSig(index, 1).UserObject = new Action(routeAction);
+ owner.StringInputSig(index, 1).StringValue = SourceItem.PreferredName;
+ }
+
+ public void RegisterForSourceChange(IHasCurrentSourceInfoChange room)
+ {
+ room.CurrentSingleSourceChange -= room_CurrentSourceInfoChange;
+ room.CurrentSingleSourceChange += room_CurrentSourceInfoChange;
+ }
+
+ void room_CurrentSourceInfoChange(EssentialsRoomBase room, SourceListItem info, ChangeType type)
+ {
+ if (type == ChangeType.WillChange && info == SourceItem)
+ ClearFeedback();
+ else if (type == ChangeType.DidChange && info == SourceItem)
+ SetFeedback();
+ }
+
+ ///
+ /// Called by SRL to release all referenced objects
+ ///
+ public override void Clear()
+ {
+ Owner.BoolInputSig(Index, 1).UserObject = null;
+ Owner.StringInputSig(Index, 1).StringValue = "";
+ }
+
+ ///
+ /// Sets the selected feedback on the button
+ ///
+ public void SetFeedback()
+ {
+ Owner.BoolInputSig(Index, 1).BoolValue = true;
+ }
+
+ ///
+ /// Clears the selected feedback on the button
+ ///
+ public void ClearFeedback()
+ {
+ Owner.BoolInputSig(Index, 1).BoolValue = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Release Package/PepperDashEssentials.cpz b/Release Package/PepperDashEssentials.cpz
index e9daf0be..7451c8ca 100644
Binary files a/Release Package/PepperDashEssentials.cpz and b/Release Package/PepperDashEssentials.cpz differ
diff --git a/Release Package/PepperDashEssentials.dll b/Release Package/PepperDashEssentials.dll
index c8f15a7c..679cdf05 100644
Binary files a/Release Package/PepperDashEssentials.dll and b/Release Package/PepperDashEssentials.dll differ