merge dev 2.0.0

This commit is contained in:
Andrew Welker
2024-02-05 13:33:25 -06:00
243 changed files with 1269 additions and 45207 deletions

View File

@@ -1,29 +0,0 @@
extern alias Full;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.DSP;
using System;
using System.Text.RegularExpressions;
namespace PepperDash.Essentials
{
/// <summary>
///
/// </summary>
public class EssentialsRoomVolumesConfig
{
public EssentialsVolumeLevelConfig Master { get; set; }
public EssentialsVolumeLevelConfig Program { get; set; }
public EssentialsVolumeLevelConfig AudioCallRx { get; set; }
public EssentialsVolumeLevelConfig AudioCallTx { get; set; }
}
/// <summary>
///
/// </summary>
public class EssentialsVolumeLevelConfig
{
public string DeviceKey { get; set; }
public string Label { get; set; }
public int Level { get; set; }
}
}

View File

@@ -1,4 +1,4 @@
extern alias Full;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Reflection;
@@ -34,6 +34,29 @@ namespace PepperDash.Essentials
DeviceManager.Initialize(this);
SecretsManager.Initialize();
SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true;
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
}
private System.Reflection.Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
{
var assemblyName = new System.Reflection.AssemblyName(args.Name).Name;
if (assemblyName == "PepperDash_Core")
{
return System.Reflection.Assembly.LoadFrom("PepperDashCore.dll");
}
if (assemblyName == "PepperDash_Essentials_Core")
{
return System.Reflection.Assembly.LoadFrom("PepperDash.Essentials.Core.dll");
}
if (assemblyName == "Essentials Devices Common")
{
return System.Reflection.Assembly.LoadFrom("PepperDash.Essentials.Devices.Common.dll");
}
return null;
}
/// <summary>
@@ -146,22 +169,11 @@ namespace PepperDash.Essentials
string directoryPrefix;
directoryPrefix = Crestron.SimplSharp.CrestronIO.Directory.GetApplicationRootDirectory();
directoryPrefix = Directory.GetApplicationRootDirectory();
//var assembly = Assembly.GetExecutingAssembly();
var fullVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
//Debug.Console(0, "Assembly Name: ", assembly.FullName);
//var fullVersion = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false);
//if (fullVersion.Length == 0)
//{
// Debug.Console(0, "***********************Unable to determine version.***********************");
//}
//AssemblyInformationalVersionAttribute fullVersionAtt = fullVersion[0] as AssemblyInformationalVersionAttribute;
//Debug.Console(0, "Full Version: {0}", fullVersionAtt.InformationalVersion);
Global.SetAssemblyVersion(fullVersion);
//Global.SetAssemblyVersion(fullVersionAtt.InformationalVersion);
@@ -458,63 +470,65 @@ namespace PepperDash.Essentials
return;
}
uint fusionIpId = 0xf1;
// uint fusionIpId = 0xf1;
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
{
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom;
if (room != null)
{
// default to no join map key
string fusionJoinMapKey = string.Empty;
if (room.Config.Properties["fusion"] != null)
/*
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom;
if (room != null)
{
Debug.Console(2, "Custom Fusion config found. Using custom values");
// default to no join map key
string fusionJoinMapKey = string.Empty;
var fusionConfig = room.Config.Properties["fusion"].ToObject<EssentialsRoomFusionConfig>();
if (fusionConfig != null)
if (room.Config.Properties["fusion"] != null)
{
fusionIpId = fusionConfig.IpIdInt;
fusionJoinMapKey = fusionConfig.JoinMapKey;
}
}
Debug.Console(2, "Custom Fusion config found. Using custom values");
AddRoomAndBuildMC(room);
var fusionConfig = room.Config.Properties["fusion"].ToObject<EssentialsRoomFusionConfig>();
if (room is IEssentialsHuddleSpaceRoom)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey));
}
else if (room is IEssentialsHuddleVtc1Room)
{
if (!(room is EssentialsCombinedHuddleVtc1Room))
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
if (fusionConfig != null)
{
fusionIpId = fusionConfig.IpIdInt;
fusionJoinMapKey = fusionConfig.JoinMapKey;
}
}
AddRoomAndBuildMC(room);
if (room is IEssentialsHuddleSpaceRoom)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey));
}
else if (room is IEssentialsHuddleVtc1Room)
{
if (!(room is EssentialsCombinedHuddleVtc1Room))
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
}
}
else if (room is EssentialsTechRoom)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey));
}
fusionIpId += 1;
}
else if (room is EssentialsTechRoom)
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key);
}
fusionIpId += 1;
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key);
}
*/
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");

View File

@@ -1,72 +0,0 @@
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.Core.Config;
using PepperDash.Essentials.Core.Routing;
namespace PepperDash.Essentials
{
public class Amplifier : EssentialsDevice, IRoutingSinkNoSwitching
{
public event SourceInfoChangeHandler CurrentSourceChange;
public string CurrentSourceInfoKey { get; set; }
public SourceListItem CurrentSourceInfo
{
get
{
return _CurrentSourceInfo;
}
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
public RoutingInputPort AudioIn { get; private set; }
public Amplifier(string key, string name)
: base(key, name)
{
AudioIn = new RoutingInputPort(RoutingPortNames.AnyAudioIn, eRoutingSignalType.Audio,
eRoutingPortConnectionType.None, null, this);
InputPorts = new RoutingPortCollection<RoutingInputPort> { AudioIn };
}
#region IRoutingInputs Members
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
#endregion
}
public class AmplifierFactory : EssentialsDeviceFactory<Amplifier>
{
public AmplifierFactory()
{
TypeNames = new List<string>() { "amplifier" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new Amplifier Device");
return new Amplifier(dc.Key, dc.Name);
}
}
}

View File

@@ -1,4 +1,4 @@
extern alias Full;
using System;
using System.Collections.Generic;
@@ -8,8 +8,8 @@ using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Crestron.SimplSharp.Reflection;
using Full.Newtonsoft.Json;
using Full.Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;

View File

@@ -1,358 +0,0 @@
using System;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.Fusion;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Fusion;
namespace PepperDash.Essentials.Fusion
{
public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase
{
BooleanSigData CodecIsInCall;
public EssentialsHuddleVtc1FusionController(IEssentialsHuddleVtc1Room room, uint ipId, string joinMapKey)
: base(room, ipId, joinMapKey)
{
}
/// <summary>
/// Called in base class constructor before RVI and GUID files are built
/// </summary>
protected override void ExecuteCustomSteps()
{
SetUpCodec();
}
/// <summary>
/// Creates a static asset for the codec and maps the joins to the main room symbol
/// </summary>
void SetUpCodec()
{
try
{
var codec = (Room as IEssentialsHuddleVtc1Room).VideoCodec;
if (codec == null)
{
Debug.Console(1, this, "Cannot link codec to Fusion because codec is null");
return;
}
codec.UsageTracker = new UsageTracking(codec);
codec.UsageTracker.UsageIsTracked = true;
codec.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
var codecPowerOnAction = new Action<bool>(b => { if (!b) codec.StandbyDeactivate(); });
var codecPowerOffAction = new Action<bool>(b => { if (!b) codec.StandbyActivate(); });
// Map FusionRoom Attributes:
// Codec volume
var codecVolume = FusionRoom.CreateOffsetUshortSig(JoinMap.VolumeFader1.JoinNumber, JoinMap.VolumeFader1.AttributeName, eSigIoMask.InputOutputSig);
codecVolume.OutputSig.UserObject = new Action<ushort>(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
(codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
// In Call Status
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(JoinMap.VcCodecInCall.JoinNumber, JoinMap.VcCodecInCall.AttributeName, eSigIoMask.InputSigOnly);
codec.CallStatusChange += new EventHandler<PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
// Online status
if (codec is ICommunicationMonitor)
{
var c = codec as ICommunicationMonitor;
var codecOnline = FusionRoom.CreateOffsetBoolSig(JoinMap.VcCodecOnline.JoinNumber, JoinMap.VcCodecOnline.AttributeName, eSigIoMask.InputSigOnly);
codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
c.CommunicationMonitor.StatusChange += (o, a) =>
{
codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
};
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, JoinMap.VcCodecOnline.AttributeName);
}
// Codec IP Address
bool codecHasIpInfo = false;
var codecComm = codec.Communication;
string codecIpAddress = string.Empty;
int codecIpPort = 0;
StringSigData codecIpAddressSig;
StringSigData codecIpPortSig;
if(codecComm is GenericSshClient)
{
codecIpAddress = (codecComm as GenericSshClient).Hostname;
codecIpPort = (codecComm as GenericSshClient).Port;
codecHasIpInfo = true;
}
else if (codecComm is GenericTcpIpClient)
{
codecIpAddress = (codecComm as GenericTcpIpClient).Hostname;
codecIpPort = (codecComm as GenericTcpIpClient).Port;
codecHasIpInfo = true;
}
if (codecHasIpInfo)
{
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(JoinMap.VcCodecIpAddress.JoinNumber, JoinMap.VcCodecIpAddress.AttributeName, eSigIoMask.InputSigOnly);
codecIpAddressSig.InputSig.StringValue = codecIpAddress;
codecIpPortSig = FusionRoom.CreateOffsetStringSig(JoinMap.VcCodecIpPort.JoinNumber, JoinMap.VcCodecIpPort.AttributeName, eSigIoMask.InputSigOnly);
codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
}
var tempAsset = new FusionAsset();
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(c => c.Key.Equals(codec.Key));
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
{
tempAsset = FusionStaticAssets[deviceConfig.Uid];
}
else
{
// Create a new asset
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), codec.Name, "Codec", "");
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Codec", tempAsset.InstanceId);
codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
// TODO: Map relevant attributes on asset symbol
codecAsset.TrySetMakeModel(codec);
codecAsset.TryLinkAssetErrorToCommunication(codec);
}
catch (Exception e)
{
Debug.Console(1, this, "Error setting up codec in Fusion: {0}", e);
}
}
void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e)
{
var codec = (Room as IEssentialsHuddleVtc1Room).VideoCodec;
CodecIsInCall.InputSig.BoolValue = codec.IsInCall;
}
// These methods are overridden because they access the room class which is of a different type
protected override void CreateSymbolAndBasicSigs(uint ipId)
{
Debug.Console(0, this, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId);
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
FusionRoom.Register();
FusionRoom.FusionStateChange += FusionRoom_FusionStateChange;
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += FusionRoomSchedule_DeviceExtenderSigChange;
FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange;
FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange;
CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(CreateAdHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
// Room to fusion room
Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
// Moved to
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.AttributeName, eSigIoMask.InputSigOnly);
// Don't think we need to get current status of this as nothing should be alive yet.
(Room as IEssentialsHuddleVtc1Room).CurrentSourceChange += Room_CurrentSourceInfoChange;
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as IEssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as IEssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey));
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
}
protected override void SetUpSources()
{
// Sources
var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as IEssentialsHuddleVtc1Room).SourceListKey);
if (dict != null)
{
// NEW PROCESS:
// Make these lists and insert the fusion attributes by iterating these
var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
uint i = 1;
foreach (var kvp in setTopBoxes)
{
TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.AttributeName + " " + i, JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > JoinMap.Display1SetTopBoxSourceStart.JoinSpan) // We only have five spots
break;
}
var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
i = 1;
foreach (var kvp in discPlayers)
{
TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.AttributeName + " " + i, JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 5) // We only have five spots
break;
}
var laptops = dict.Where(d => d.Value.SourceDevice is Core.Devices.Laptop);
i = 1;
foreach (var kvp in laptops)
{
TryAddRouteActionSigs(JoinMap.Display1LaptopSourceStart.AttributeName + " " + i, JoinMap.Display1LaptopSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > JoinMap.Display1LaptopSourceStart.JoinSpan) // We only have ten spots???
break;
}
foreach (var kvp in dict)
{
var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
if (usageDevice != null)
{
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
usageDevice.UsageTracker.UsageIsTracked = true;
usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
}
}
}
else
{
Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
(Room as IEssentialsHuddleVtc1Room).SourceListKey, Room.Key);
}
}
protected override void SetUpDisplay()
{
try
{
//Setup Display Usage Monitoring
var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
// Consider updating this in multiple display systems
foreach (DisplayBase display in displays)
{
display.UsageTracker = new UsageTracking(display);
display.UsageTracker.UsageIsTracked = true;
display.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
}
var defaultDisplay = (Room as IEssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase;
if (defaultDisplay == null)
{
Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
return;
}
var dispPowerOnAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOn(); });
var dispPowerOffAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOff(); });
// Display to fusion room sigs
FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
var defaultDisplayTwoWay = defaultDisplay as IHasPowerControlWithFeedback;
if (defaultDisplayTwoWay != null)
{
defaultDisplayTwoWay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
}
if (defaultDisplay is IDisplayUsage)
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
MapDisplayToRoomJoins(1, JoinMap.Display1Start.JoinNumber, defaultDisplay);
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
//Check for existing asset in GUIDs collection
var tempAsset = new FusionAsset();
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
{
tempAsset = FusionStaticAssets[deviceConfig.Uid];
}
else
{
// Create a new asset
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
var defaultTwoWayDisplay = defaultDisplay as IHasPowerControlWithFeedback;
if (defaultTwoWayDisplay != null)
{
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
if (defaultDisplay is IDisplayUsage)
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
}
// Use extension methods
dispAsset.TrySetMakeModel(defaultDisplay);
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
}
catch (Exception e)
{
Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
}
}
protected override void MapDisplayToRoomJoins(int displayIndex, uint joinOffset, DisplayBase display)
{
string displayName = string.Format("Display {0} - ", displayIndex);
if (display == (Room as IEssentialsHuddleVtc1Room).DefaultDisplay)
{
// Power on
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOn(); });
// Power Off
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOff(); }); ;
var displayTwoWay = display as IHasPowerControlWithFeedback;
if (displayTwoWay != null)
{
displayTwoWay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
displayTwoWay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
}
// Current Source
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b => { if (!b) (Room as IEssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey); }); ;
}
}
}
}

View File

@@ -1,106 +0,0 @@
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.Core.Config;
using PepperDash.Essentials.Core.Fusion;
namespace PepperDash.Essentials.Fusion
{
public class EssentialsTechRoomFusionSystemController : EssentialsHuddleSpaceFusionSystemControllerBase
{
public EssentialsTechRoomFusionSystemController(EssentialsTechRoom room, uint ipId, string joinMapKey)
: base(room, ipId, joinMapKey)
{
}
protected override void SetUpDisplay()
{
try
{
var displays = (Room as EssentialsTechRoom).Displays;
Debug.Console(1, this, "Setting up Static Assets for {0} Displays", displays.Count);
foreach (var display in displays.Values.Cast<DisplayBase>())
{
var disp = display; // Local scope variable
Debug.Console(2, this, "Setting up Static Asset for {0}", disp.Key);
disp.UsageTracker = new UsageTracking(disp) { UsageIsTracked = true };
disp.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
var dispPowerOnAction = new Action<bool>(b =>
{
if (!b)
{
disp.PowerOn();
}
});
var dispPowerOffAction = new Action<bool>(b =>
{
if (!b)
{
disp.PowerOff();
}
});
var deviceConfig = ConfigReader.ConfigObject.GetDeviceForKey(disp.Key);
FusionAsset tempAsset;
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
{
// Used existing asset
tempAsset = FusionStaticAssets[deviceConfig.Uid];
}
else
{
// Create a new asset
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom),
disp.Name, "Display", "");
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display",
tempAsset.InstanceId);
if (dispAsset != null)
{
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
// Use extension methods
dispAsset.TrySetMakeModel(disp);
dispAsset.TryLinkAssetErrorToCommunication(disp);
}
var defaultTwoWayDisplay = disp as IHasPowerControlWithFeedback;
if (defaultTwoWayDisplay != null)
{
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
if (disp is IDisplayUsage)
{
(disp as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
}
if(dispAsset != null)
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
}
}
}
catch (Exception e)
{
Debug.Console(1, this, "Error setting up displays in Fusion: {0}", e);
}
}
}
}

View File

@@ -1,12 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectType>Program</ProjectType>
<Configurations>Debug;Release;Debug 4.7.2</Configurations>
</PropertyGroup>
<PropertyGroup>
<RootNamespace>PepperDash.Essentials</RootNamespace>
<AssemblyName>PepperDash.Essentials</AssemblyName>
<TargetFramework>net472</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<TargetFrameworks>net472;net6</TargetFrameworks>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<OutputPath>bin\$(Configuration)\</OutputPath>
<Title>PepperDash Essentials</Title>
<PackageId>PepperDashEssentials</PackageId>
@@ -15,14 +16,12 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 4.7.2|AnyCPU'">
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<None Include="Example Configuration\EssentialsHuddleSpaceRoom\configurationFile-HuddleSpace-2-Source.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@@ -47,11 +46,8 @@
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.20.31" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2">
<Aliases>Full</Aliases>
</PackageReference>
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-375" />
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.20.42" />
<PackageReference Include="PepperDashCore" Version="2.0.0-beta-383" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />

View File

@@ -1,17 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsDualDisplayRoomPropertiesConfig : EssentialsNDisplayRoomPropertiesConfig
{
}
}

View File

@@ -1,44 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
using Full.Newtonsoft.Json.Converters;
using Full.Newtonsoft.Json.Linq;
namespace PepperDash.Essentials.Room.Config
{
/// <summary>
///
/// </summary>
public class EssentialsHuddleRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{
/// <summary>
/// The key of the default display device
/// </summary>
[JsonProperty("defaultDisplayKey")]
public string DefaultDisplayKey { get; set; }
/// <summary>
/// The key of the default audio device
/// </summary>
[JsonProperty("defaultAudioKey")]
public string DefaultAudioKey { get; set; }
/// <summary>
/// The key of the source list for the room
/// </summary>
[JsonProperty("sourceListKey")]
public string SourceListKey { get; set; }
/// <summary>
/// The key of the default source item from the source list
/// </summary>
[JsonProperty("defaultSourceItem")]
public string DefaultSourceItem { get; set; }
}
}

View File

@@ -1,19 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsHuddleVtc1PropertiesConfig : EssentialsConferenceRoomPropertiesConfig
{
[JsonProperty("defaultDisplayKey")]
public string DefaultDisplayKey { get; set; }
}
}

View File

@@ -1,41 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using Full.Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
/// <summary>
///
/// </summary>
public class EssentialsNDisplayRoomPropertiesConfig : EssentialsConferenceRoomPropertiesConfig
{
[JsonProperty("defaultAudioBehavior")]
public string DefaultAudioBehavior { get; set; }
[JsonProperty("defaultVideoBehavior")]
public string DefaultVideoBehavior { get; set; }
[JsonProperty("displays")]
public Dictionary<eSourceListItemDestinationTypes, DisplayItem> Displays { get; set; }
public EssentialsNDisplayRoomPropertiesConfig()
{
Displays = new Dictionary<eSourceListItemDestinationTypes, DisplayItem>();
}
}
public class DisplayItem : IKeyName
{
public string Key { get; set; }
public string Name { get; set; }
}
}

View File

@@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Room.Config
{
/// <summary>
///
/// </summary>
public class EssentialsPresentationRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{
public string DefaultAudioBehavior { get; set; }
public string DefaultAudioKey { get; set; }
public string DefaultVideoBehavior { get; set; }
public List<string> DisplayKeys { get; set; }
public string SourceListKey { get; set; }
public bool HasDsp { get; set; }
public EssentialsPresentationRoomPropertiesConfig()
{
DisplayKeys = new List<string>();
}
}
}

View File

@@ -1,413 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsRoomConfigHelper
{
/// <summary>
/// Returns a room object from this config data
/// </summary>
/// <returns></returns>
public static IKeyed GetRoomObject(DeviceConfig roomConfig)
{
var typeName = roomConfig.Type.ToLower();
switch (typeName)
{
case "huddle" :
{
return new EssentialsHuddleSpaceRoom(roomConfig);
}
case "huddlevtc1" :
{
return new EssentialsHuddleVtc1Room(roomConfig);
}
case "ddvc01bridge" :
{
return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing.
}
case "dualdisplay" :
{
return new EssentialsDualDisplayRoom(roomConfig);
}
case "combinedhuddlevtc1" :
{
return new EssentialsCombinedHuddleVtc1Room(roomConfig);
}
case "techroom" :
{
return new EssentialsTechRoom(roomConfig);
}
default :
{
return Core.DeviceFactory.GetDevice(roomConfig);
}
}
}
/// <summary>
/// Gets and operating, standalone emergegncy object that can be plugged into a room.
/// Returns null if there is no emergency defined
/// </summary>
public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, IEssentialsRoom room)
{
// This emergency
var emergency = props.Emergency;
if (emergency != null)
{
//switch on emergency type here. Right now only contact and shutdown
var e = new EssentialsRoomEmergencyContactClosure(room.Key + "-emergency", props.Emergency, room);
DeviceManager.AddDevice(e);
}
return null;
}
/// <summary>
///
/// </summary>
/// <param name="props"></param>
/// <param name="room"></param>
/// <returns></returns>
public static Core.Privacy.MicrophonePrivacyController GetMicrophonePrivacy(
EssentialsRoomPropertiesConfig props, IPrivacy room)
{
var microphonePrivacy = props.MicrophonePrivacy;
if (microphonePrivacy == null)
{
Debug.Console(0, "Cannot create microphone privacy with null properties");
return null;
}
// Get the MicrophonePrivacy device from the device manager
var mP = (DeviceManager.GetDeviceForKey(props.MicrophonePrivacy.DeviceKey) as
Core.Privacy.MicrophonePrivacyController);
// Set this room as the IPrivacy device
if (mP == null)
{
Debug.Console(0, "ERROR: Selected device {0} is not MicrophonePrivacyController", props.MicrophonePrivacy.DeviceKey);
return null;
}
mP.SetPrivacyDevice(room);
var behaviour = props.MicrophonePrivacy.Behaviour.ToLower();
if (behaviour == null)
{
Debug.Console(0, "WARNING: No behaviour defined for MicrophonePrivacyController");
return null;
}
if (behaviour == "trackroomstate")
{
// Tie LED enable to room power state
var essRoom = room as IEssentialsRoom;
essRoom.OnFeedback.OutputChange += (o, a) =>
{
if (essRoom.OnFeedback.BoolValue)
mP.EnableLeds = true;
else
mP.EnableLeds = false;
};
mP.EnableLeds = essRoom.OnFeedback.BoolValue;
}
else if (behaviour == "trackcallstate")
{
// Tie LED enable to room power state
var inCallRoom = room as IHasInCallFeedback;
inCallRoom.InCallFeedback.OutputChange += (o, a) =>
{
if (inCallRoom.InCallFeedback.BoolValue)
mP.EnableLeds = true;
else
mP.EnableLeds = false;
};
mP.EnableLeds = inCallRoom.InCallFeedback.BoolValue;
}
return mP;
}
}
/// <summary>
///
/// </summary>
public class EssentialsRoomPropertiesConfig
{
[JsonProperty("addresses")]
public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("emergency")]
public EssentialsRoomEmergencyConfig Emergency { get; set; }
[JsonProperty("help")]
public EssentialsHelpPropertiesConfig Help { get; set; }
[JsonProperty("helpMessage")]
public string HelpMessage { get; set; }
/// <summary>
/// Read this value to get the help message. It checks for the old and new config format.
/// </summary>
public string HelpMessageForDisplay
{
get
{
if(Help != null && !string.IsNullOrEmpty(Help.Message))
{
return Help.Message;
}
else
{
return HelpMessage;
}
}
}
[JsonProperty("environment")]
public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
[JsonProperty("logo")]
public EssentialsLogoPropertiesConfig LogoLight { get; set; }
[JsonProperty("logoDark")]
public EssentialsLogoPropertiesConfig LogoDark { get; set; }
[JsonProperty("microphonePrivacy")]
public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; }
[JsonProperty("occupancy")]
public EssentialsRoomOccSensorConfig Occupancy { get; set; }
[JsonProperty("oneButtonMeeting")]
public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
[JsonProperty("shutdownVacancySeconds")]
public int ShutdownVacancySeconds { get; set; }
[JsonProperty("shutdownPromptSeconds")]
public int ShutdownPromptSeconds { get; set; }
[JsonProperty("tech")]
public EssentialsRoomTechConfig Tech { get; set; }
[JsonProperty("volumes")]
public EssentialsRoomVolumesConfig Volumes { get; set; }
[JsonProperty("fusion")]
public EssentialsRoomFusionConfig Fusion { get; set; }
[JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)]
public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; }
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
/// <summary>
/// Indicates if this room represents a combination of other rooms
/// </summary>
[JsonProperty("isRoomCombinationScenario")]
public bool IsRoomCombinationScenario { get; set; }
public EssentialsRoomPropertiesConfig()
{
LogoLight = new EssentialsLogoPropertiesConfig();
LogoDark = new EssentialsLogoPropertiesConfig();
}
}
public class EssentialsRoomUiBehaviorConfig
{
[JsonProperty("disableActivityButtonsWhileWarmingCooling")]
public bool DisableActivityButtonsWhileWarmingCooling { get; set; }
}
public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{
[JsonProperty("defaultAudioKey")]
public string DefaultAudioKey { get; set; }
[JsonProperty("sourceListKey")]
public string SourceListKey { get; set; }
[JsonProperty("destinationListKey")]
public string DestinationListKey { get; set; }
[JsonProperty("defaultSourceItem")]
public string DefaultSourceItem { get; set; }
/// <summary>
/// Indicates if the room supports advanced sharing
/// </summary>
[JsonProperty("supportsAdvancedSharing")]
public bool SupportsAdvancedSharing { get; set; }
/// <summary>
/// Indicates if non-tech users can change the share mode
/// </summary>
[JsonProperty("userCanChangeShareMode")]
public bool UserCanChangeShareMode { get; set; }
}
public class EssentialsConferenceRoomPropertiesConfig : EssentialsAvRoomPropertiesConfig
{
[JsonProperty("videoCodecKey")]
public string VideoCodecKey { get; set; }
[JsonProperty("audioCodecKey")]
public string AudioCodecKey { get; set; }
}
public class EssentialsEnvironmentPropertiesConfig
{
public bool Enabled { get; set; }
[JsonProperty("deviceKeys")]
public List<string> DeviceKeys { get; set; }
public EssentialsEnvironmentPropertiesConfig()
{
DeviceKeys = new List<string>();
}
}
public class EssentialsRoomFusionConfig
{
public uint IpIdInt
{
get
{
try
{
return Convert.ToUInt32(IpId, 16);
}
catch (Exception)
{
throw new FormatException(string.Format("ERROR:Unable to convert IP ID: {0} to hex. Error:\n{1}", IpId));
}
}
}
[JsonProperty("ipId")]
public string IpId { get; set; }
[JsonProperty("joinMapKey")]
public string JoinMapKey { get; set; }
}
public class EssentialsRoomMicrophonePrivacyConfig
{
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("behaviour")]
public string Behaviour { get; set; }
}
/// <summary>
/// Properties for the help text box
/// </summary>
public class EssentialsHelpPropertiesConfig
{
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("showCallButton")]
public bool ShowCallButton { get; set; }
/// <summary>
/// Defaults to "Call Help Desk"
/// </summary>
[JsonProperty("callButtonText")]
public string CallButtonText { get; set; }
public EssentialsHelpPropertiesConfig()
{
CallButtonText = "Call Help Desk";
}
}
/// <summary>
///
/// </summary>
public class EssentialsOneButtonMeetingPropertiesConfig
{
[JsonProperty("enable")]
public bool Enable { get; set; }
}
public class EssentialsRoomAddressPropertiesConfig
{
[JsonProperty("phoneNumber")]
public string PhoneNumber { get; set; }
[JsonProperty("sipAddress")]
public string SipAddress { get; set; }
}
/// <summary>
/// Properties for the room's logo on panels
/// </summary>
public class EssentialsLogoPropertiesConfig
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
/// <summary>
/// Gets either the custom URL, a local-to-processor URL, or null if it's a default logo
/// </summary>
public string GetLogoUrlLight()
{
if (Type == "url")
return Url;
if (Type == "system")
return string.Format("http://{0}:8080/logo.png",
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
return null;
}
public string GetLogoUrlDark()
{
if (Type == "url")
return Url;
if (Type == "system")
return string.Format("http://{0}:8080/logo-dark.png",
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
return null;
}
}
/// <summary>
/// Represents occupancy sensor(s) setup for a room
/// </summary>
public class EssentialsRoomOccSensorConfig
{
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("timeoutMinutes")]
public int TimeoutMinutes { get; set; }
}
public class EssentialsRoomTechConfig
{
[JsonProperty("password")]
public string Password { get; set; }
}
}

View File

@@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Room.Config
{
/// <summary>
///
/// </summary>
public class EssentialsRoomEmergencyConfig
{
public EssentialsRoomEmergencyTriggerConfig Trigger { get; set; }
public string Behavior { get; set; }
}
/// <summary>
///
/// </summary>
public class EssentialsRoomEmergencyTriggerConfig
{
/// <summary>
/// contact,
/// </summary>
public string Type { get; set; }
/// <summary>
/// Input number if contact
/// </summary>
public int Number { get; set; }
public bool TriggerOnClose { get; set; }
}
}

View File

@@ -1,77 +0,0 @@
extern alias Full;
using System.Collections.Generic;
using Full.Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsTechRoomConfig
{
/// <summary>
/// The key of the dummy device used to enable routing
/// </summary>
[JsonProperty("dummySourceKey")]
public string DummySourceKey { get; set; }
/// <summary>
/// The keys of the displays assigned to this room
/// </summary>
[JsonProperty("displays")]
public List<string> Displays { get; set; }
/// <summary>
/// The keys of the tuners assinged to this room
/// </summary>
[JsonProperty("tuners")]
public List<string> Tuners { get; set; }
/// <summary>
/// PIN to access the room as a normal user
/// </summary>
[JsonProperty("userPin")]
public string UserPin { get; set; }
/// <summary>
/// PIN to access the room as a tech user
/// </summary>
[JsonProperty("techPin")]
public string TechPin { get; set; }
/// <summary>
/// Name of the presets file. Path prefix is assumed to be /html/presets/lists/
/// </summary>
[JsonProperty("presetsFileName")]
public string PresetsFileName { get; set; }
[JsonProperty("scheduledEvents")]
public List<ScheduledEventConfig> ScheduledEvents { get; set; }
/// <summary>
/// Indicates that the room is the primary when true
/// </summary>
[JsonProperty("isPrimary")]
public bool IsPrimary { get; set; }
/// <summary>
/// Indicates which tuners should mirror preset recall when two rooms are configured in a primary->secondary scenario
/// </summary>
[JsonProperty("mirroredTuners")]
public Dictionary<uint, string> MirroredTuners { get; set; }
[JsonProperty("helpMessage")]
public string HelpMessage { get; set; }
/// <summary>
/// Indicates the room
/// </summary>
[JsonProperty("isTvPresetsProvider")]
public bool IsTvPresetsProvider;
public EssentialsTechRoomConfig()
{
Displays = new List<string>();
Tuners = new List<string>();
ScheduledEvents = new List<ScheduledEventConfig>();
}
}
}

View File

@@ -1,32 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
public class SimplRoomPropertiesConfig : EssentialsHuddleVtc1PropertiesConfig
{
[JsonProperty("roomPhoneNumber")]
public string RoomPhoneNumber { get; set; }
[JsonProperty("roomURI")]
public string RoomURI { get; set; }
[JsonProperty("speedDials")]
public List<SimplSpeedDial> SpeedDials { get; set; }
[JsonProperty("volumeSliderNames")]
public List<string> VolumeSliderNames { get; set; }
}
public class SimplSpeedDial
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("number")]
public string Number { get; set; }
}
}

View File

@@ -1,58 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.Room
{
public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase
{
IEssentialsRoom Room;
string Behavior;
bool TriggerOnClose;
public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, IEssentialsRoom room) :
base(key)
{
Room = room;
var cs = Global.ControlSystem;
if (config.Trigger.Type.Equals("contact", StringComparison.OrdinalIgnoreCase))
{
var portNum = (uint)config.Trigger.Number;
if (portNum <= cs.NumberOfDigitalInputPorts)
{
cs.DigitalInputPorts[portNum].Register();
cs.DigitalInputPorts[portNum].StateChange += EsentialsRoomEmergencyContactClosure_StateChange;
}
}
Behavior = config.Behavior;
TriggerOnClose = config.Trigger.TriggerOnClose;
}
void EsentialsRoomEmergencyContactClosure_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
{
if (args.State && TriggerOnClose || !args.State && !TriggerOnClose)
RunEmergencyBehavior();
}
/// <summary>
///
/// </summary>
public void RunEmergencyBehavior()
{
if (Behavior.Equals("shutdown"))
Room.Shutdown();
}
}
}

View File

@@ -1,968 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials
{
public class EssentialsCombinedHuddleVtc1Room : EssentialsRoomBase, IEssentialsHuddleVtc1Room
{
private bool _codecExternalSourceChange;
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSourceChange;
//************************
// Call-related stuff
public BoolFeedback InCallFeedback { get; private set; }
///// <summary>
///// Make this more specific
///// </summary>
//public List<CodecActiveCallItem> ActiveCalls { get; private set; }
/// <summary>
/// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis
/// </summary>
public IntFeedback CallTypeFeedback { get; private set; }
/// <summary>
///
/// </summary>
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
/// <summary>
/// When something in the room is sharing with the far end or through other means
/// </summary>
public BoolFeedback IsSharingFeedback { get; private set; }
//************************
protected override Func<bool> OnFeedbackFunc
{
get
{
return () =>
{
var displays = Displays.OfType<DisplayBase>().ToList();
var val = CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route
&& displays.Count > 0;
//&& disp.PowerIsOnFeedback.BoolValue;
return val;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () => Displays.OfType<TwoWayDisplayBase>().Any((d) => d.IsWarmingUpFeedback.BoolValue);
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () => Displays.OfType<TwoWayDisplayBase>().Any((d) => d.IsCoolingDownFeedback.BoolValue);
}
}
public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; }
private List<IRoutingSinkWithSwitching> Displays;
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
public VideoCodecBase VideoCodec { get; private set; }
public AudioCodecBase AudioCodec { get; private set; }
public bool ExcludeFromGlobalFunctions { get; set; }
public string DefaultSourceItem { get; set; }
public ushort DefaultVolume { get; set; }
/// <summary>
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string LastSourceKey;
/// <summary>
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
/// tag to device.
/// </summary>
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;
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _CurrentSourceInfo; }
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
// 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(_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(_CurrentSourceInfo, ChangeType.DidChange);
var vc = VideoCodec as IHasExternalSourceSwitching;
if (vc != null && !_codecExternalSourceChange)
{
vc.SetSelectedSource(CurrentSourceInfoKey);
}
_codecExternalSourceChange = false;
}
}
SourceListItem _CurrentSourceInfo;
public string CurrentSourceInfoKey { get; set; }
/// <summary>
/// "codecOsd"
/// </summary>
public string DefaultCodecRouteString { get { return "codecOsd"; } }
/// <summary>
/// Temporary implementation. Returns the schedule-ready object or null if none. Fow now,
/// always returns the VideoCodec if it is capable
/// </summary>
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
CCriticalSection SourceSelectLock = new CCriticalSection();
public EssentialsCombinedHuddleVtc1Room(DeviceConfig config)
: base(config)
{
try
{
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
(config.Properties.ToString());
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null)
throw new ArgumentNullException("codec cannot be null");
AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null)
Debug.Console(0, this, "No Audio Codec Found");
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls;
Displays = new List<IRoutingSinkWithSwitching>();
Initialize();
}
catch (Exception e)
{
Debug.Console(1, this, "Error building room: \n{0}", e);
}
}
public override void Initialize()
{
try
{
//if (DefaultAudioDevice is IBasicVolumeControls)
// DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
//else if (DefaultAudioDevice is IHasVolumeDevice)
// DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
//CurrentVolumeControls = DefaultVolumeControls;
//// Combines call feedback from both codecs if available
//InCallFeedback = new BoolFeedback(() =>
//{
// bool inAudioCall = false;
// bool inVideoCall = false;
// if (AudioCodec != null)
// inAudioCall = AudioCodec.IsInCall;
// if (VideoCodec != null)
// inVideoCall = VideoCodec.IsInCall;
// if (inAudioCall || inVideoCall)
// return true;
// else
// return false;
//});
//SetupDisplays();
//// Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback
//this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
//Debug.Console(2, this, "Microphone Privacy Config evaluated.");
//// Get emergency object, if any
//this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
//Debug.Console(2, this, "Emergency Config evaluated.");
//VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
//VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); };
//if (AudioCodec != null)
// AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
//IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
//VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate();
//// link privacy to VC (for now?)
//PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
//VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate();
//CallTypeFeedback = new IntFeedback(() => 0);
SetSourceListKey();
//EnablePowerOnToLastSource = true;
}
catch (Exception e)
{
Debug.Console(0, this, "Error Initializing Room: {0}", e);
}
}
private void SetupDisplays()
{
//DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
var destinationList = ConfigReader.ConfigObject.DestinationLists[PropertiesConfig.DestinationListKey];
Displays.Clear();
foreach (var destination in destinationList)
{
var dest = destination.Value.SinkDevice as IRoutingSinkWithSwitching;
if (dest != null)
{
Displays.Add(dest);
}
var display = dest as DisplayBase;
if (display != null)
{
// Link power, warming, cooling to display
var dispTwoWay = display as IHasPowerControlWithFeedback;
if (dispTwoWay != null)
{
dispTwoWay.PowerIsOnFeedback.OutputChange -= PowerIsOnFeedback_OutputChange;
dispTwoWay.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
if (dispTwoWay.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
}
display.IsWarmingUpFeedback.OutputChange -= IsWarmingUpFeedback_OutputChange;
display.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
display.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange;
display.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
}
}
}
void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
IsCoolingDownFeedback.FireUpdate();
}
void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
IsWarmingUpFeedback.FireUpdate();
if (!IsWarmingUpFeedback.BoolValue)
(CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
}
void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var dispTwoWay = sender as IHasPowerControlWithFeedback;
if (dispTwoWay != null && dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
//if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
// CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
}
private void SetSourceListKey()
{
if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey))
{
SetSourceListKey(PropertiesConfig.SourceListKey);
}
else
{
SetSourceListKey(Key);
}
SetUpVideoCodec();
}
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>(config.Properties.ToString());
if (newPropertiesConfig != null)
PropertiesConfig = newPropertiesConfig;
ConfigWriter.UpdateRoomConfig(config);
}
public override bool Deactivate()
{
// Stop listining to this event when room deactivated
VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange;
// Clear occupancy
RoomOccupancy = null;
Debug.Console(0, this, "Room '{0}' Deactivated", Name);
return base.Deactivate();
}
public override bool CustomActivate()
{
try
{
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
else if (DefaultAudioDevice is IHasVolumeDevice)
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
// Combines call feedback from both codecs if available
InCallFeedback = new BoolFeedback(() =>
{
bool inAudioCall = false;
bool inVideoCall = false;
if (AudioCodec != null)
inAudioCall = AudioCodec.IsInCall;
if (VideoCodec != null)
inVideoCall = VideoCodec.IsInCall;
if (inAudioCall || inVideoCall)
return true;
else
return false;
});
SetupDisplays();
// Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback
this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
Debug.Console(2, this, "Microphone Privacy Config evaluated.");
// Get emergency object, if any
this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
Debug.Console(2, this, "Emergency Config evaluated.");
if (AudioCodec != null)
{
AudioCodec.CallStatusChange -= AudioCodec_CallStatusChange;
AudioCodec.CallStatusChange += AudioCodec_CallStatusChange;
}
VideoCodec.CallStatusChange -= VideoCodec_CallStatusChange;
VideoCodec.CallStatusChange += VideoCodec_CallStatusChange;
VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange;
VideoCodec.IsReadyChange += VideoCodec_IsReadyChange;
VideoCodec.SharingContentIsOnFeedback.OutputChange -= SharingContentIsOnFeedback_OutputChange;
VideoCodec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange;
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
// link privacy to VC (for now?)
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
VideoCodec.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange;
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange;
CallTypeFeedback = new IntFeedback(() => 0);
SetSourceListKey();
EnablePowerOnToLastSource = true;
// Add Occupancy object from config
if (PropertiesConfig.Occupancy != null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room");
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
}
this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight();
this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark();
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
}
catch (Exception e)
{
Debug.Console(0, this, "Error Activiating Room: {0}", e);
}
Debug.Console(0, this, "Room '{0}' Activated", Name);
return base.CustomActivate();
}
void AudioCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
InCallFeedback.FireUpdate();
}
void PrivacyModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PrivacyModeIsOnFeedback.FireUpdate();
}
void VideoCodec_IsReadyChange(object sender, EventArgs e)
{
SetUpVideoCodec();
}
void SetUpVideoCodec()
{
SetCodecExternalSources();
SetCodecBranding();
}
void VideoCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
InCallFeedback.FireUpdate();
}
void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
IsSharingFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
protected override void EndShutdown()
{
VideoCodec.EndAllCalls();
SetDefaultLevels();
RunDefaultPresentRoute();
CrestronEnvironment.Sleep(1000);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
RunRouteAction("roomOff");
VideoCodec.StopSharing();
VideoCodec.StandbyActivate();
}
/// <summary>
/// Routes the default source item, if any. Returns true when default route exists
/// </summary>
public override bool RunDefaultPresentRoute()
{
if (DefaultSourceItem != null)
RunRouteAction(DefaultSourceItem);
return DefaultSourceItem != null;
}
/// <summary>
/// Sets up the room when started into call mode without presenting a source
/// </summary>
/// <returns></returns>
public bool RunDefaultCallRoute()
{
RunRouteAction(DefaultCodecRouteString);
return true;
}
public void RunRouteActionCodec(string routeKey, string sourceListKey)
{
_codecExternalSourceChange = true;
RunRouteAction(routeKey, sourceListKey);
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
public void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, new Action(() => { }));
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey)
{
if (string.IsNullOrEmpty(sourceListKey))
{
Debug.Console(1, this, "No sourceListKey present. RunRouteAction assumes default source list.");
RunRouteAction(routeKey, new Action(() => { }));
}
else
{
Debug.Console(1, this, "sourceListKey present but not yet implemented");
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback)
{
if (string.IsNullOrEmpty(sourceListKey))
{
RunRouteAction(routeKey, successCallback);
}
else
throw new NotImplementedException();
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, Action successCallback)
{
// Run this on a separate thread
new CTimer(o =>
{
// try to prevent multiple simultaneous selections
SourceSelectLock.TryEnter();
try
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "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;
}
// End usage timer on last source
if (!string.IsNullOrEmpty(LastSourceKey))
{
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
if (usageLastSource != null && usageLastSource.UsageTracker != null)
{
try
{
// There MAY have been failures in here. Protect
usageLastSource.UsageTracker.EndDeviceUsage();
}
catch (Exception e)
{
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking:\r{0}", e);
}
}
}
// Let's run it
var item = dict[routeKey];
if (routeKey.ToLower() != "roomoff")
{
LastSourceKey = routeKey;
}
else
CurrentSourceInfoKey = null;
// hand off the individual routes to this helper
foreach (var route in item.RouteList)
DoRouteItem(route);
// Start usage timer on routed source
var usageNewSource = item.SourceDevice as IUsageTracking;
if (usageNewSource != null && usageNewSource.UsageTracker != null) // Have to make sure there is a usage tracker!
{
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
}
// See if this can be moved into common, base-class method -------------
// Set volume control, 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;
}
if (volDev != CurrentVolumeControls)
{
// zero the volume on the device we are leaving.
// Set the volume to default on device we are entering
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
vd.SetVolume(0);
}
CurrentVolumeControls = volDev;
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
vd.SetVolume(vol);
}
}
// -----------------------------------------------------------------------
// 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();
if (OnFeedback.BoolValue)
{
if (VideoCodec.UsageTracker.InUseTracker.InUseFeedback.BoolValue)
{
Debug.Console(1, this, "Video Codec in use, deactivating standby on codec");
VideoCodec.StandbyDeactivate();
}
if (VideoCodec.StandbyIsOnFeedback.BoolValue)
{
VideoCodec.StandbyDeactivate();
}
else
{
Debug.Console(1, this, "Video codec not in standby. No need to wake.");
}
}
else
{
Debug.Console(1, this, "Room OnFeedback state: {0}", OnFeedback.BoolValue);
}
// report back when done
if (successCallback != null)
successCallback();
}
catch (Exception e)
{
Debug.Console(1, this, "ERROR in routing: {0}", e);
}
SourceSelectLock.Leave();
}, 0); // end of CTimer
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
void DoRouteItem(SourceRouteListItem route)
{
// if there is a $defaultAll on route, run two separate
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
{
foreach (var display in Displays)
{
var tempVideo = new SourceRouteListItem
{
DestinationKey = display.Key,
SourceKey = route.SourceKey,
Type = eRoutingSignalType.Video
};
DoRoute(tempVideo);
}
}
else
DoRoute(route);
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
bool DoRoute(SourceRouteListItem route)
{
IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice as IRoutingSink;
//else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
// dest = DefaultDisplay;
else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
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 IHasPowerControl)
(dest as IHasPowerControl).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;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//Implement this
}
/// <summary>
/// Does what it says
/// </summary>
public override void SetDefaultLevels()
{
Debug.Console(1, this, "Restoring default levels");
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (vc != null)
vc.SetVolume(DefaultVolume);
}
/// <summary>
/// Will power the room on with the last-used source
/// </summary>
public override void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(LastSourceKey);
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
/// </summary>
public static void AllRoomsOff()
{
var allRooms = DeviceManager.AllDevices.Where(d =>
d is IEssentialsRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
(room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
}
/// <summary>
/// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
/// </summary>
private void SetCodecExternalSources()
{
var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
if (videoCodecWithExternalSwitching == null || !videoCodecWithExternalSwitching.ExternalSourceListEnabled)
{
return;
}
try
{
// Get the tie line that the external switcher is connected to
string codecInputConnectorName = ConfigReader.ConfigObject.TieLines.SingleOrDefault(
x => x.DestinationKey == VideoCodec.Key && x.DestinationPort == videoCodecWithExternalSwitching.ExternalSourceInputPort).DestinationPort;
videoCodecWithExternalSwitching.ClearExternalSources();
videoCodecWithExternalSwitching.RunRouteAction = RunRouteActionCodec;
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
foreach (var kvp in srcList)
{
var srcConfig = kvp.Value;
if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff")
{
videoCodecWithExternalSwitching.AddExternalSource(codecInputConnectorName, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop);
videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready);
}
}
Debug.Console(1, this, "Successfully set up codec external sources for room: {0}", Name);
}
catch (Exception e)
{
Debug.Console(2, this, "Error setting codec external sources: {0}", e);
}
}
private void SetCodecBranding()
{
var vcWithBranding = VideoCodec as IHasBranding;
if (vcWithBranding == null) return;
Debug.Console(1, this, "Setting Codec Branding");
vcWithBranding.InitializeBranding(Key);
}
#region IPrivacy Members
public void PrivacyModeOff()
{
VideoCodec.PrivacyModeOff();
}
public void PrivacyModeOn()
{
VideoCodec.PrivacyModeOn();
}
public void PrivacyModeToggle()
{
VideoCodec.PrivacyModeToggle();
}
#endregion
}
}

View File

@@ -1,675 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials
{
public class EssentialsDualDisplayRoom : EssentialsNDisplayRoomBase, IHasCurrentVolumeControls,
IRunRouteAction, IPrivacy, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasInCallFeedback
{
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public EssentialsDualDisplayRoomPropertiesConfig PropertiesConfig { get; private set; }
//************************
// Call-related stuff
public BoolFeedback InCallFeedback { get; private set; }
/// <summary>
/// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis
/// </summary>
public IntFeedback CallTypeFeedback { get; private set; }
/// <summary>
///
/// </summary>
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
/// <summary>
/// When something in the room is sharing with the far end or through other means
/// </summary>
public BoolFeedback IsSharingFeedback { get; private set; }
public IRoutingSinkWithSwitching LeftDisplay { get; private set; }
public IRoutingSinkWithSwitching RightDisplay { get; private set; }
protected override Func<bool> OnFeedbackFunc
{
get
{
return () =>
{
var leftDisp = LeftDisplay as DisplayBase;
var rightDisp = RightDisplay as DisplayBase;
var val = leftDisp != null && leftDisp.CurrentSourceInfo != null
&& leftDisp.CurrentSourceInfo.Type == eSourceListItemType.Route
&& rightDisp != null && rightDisp.CurrentSourceInfo != null
&& rightDisp.CurrentSourceInfo.Type == eSourceListItemType.Route;
return val;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () =>
{
var leftDisp = LeftDisplay as DisplayBase;
var rightDisp = RightDisplay as DisplayBase;
if (leftDisp != null && RightDisplay != null)
return leftDisp.IsWarmingUpFeedback.BoolValue || rightDisp.IsWarmingUpFeedback.BoolValue;
else
return false;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () =>
{
var leftDisp = LeftDisplay as DisplayBase;
var rightDisp = RightDisplay as DisplayBase;
if (leftDisp != null && RightDisplay != null)
return leftDisp.IsCoolingDownFeedback.BoolValue || rightDisp.IsCoolingDownFeedback.BoolValue;
else
return false;
};
}
}
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
public VideoCodecBase VideoCodec { get; private set; }
public AudioCodecBase AudioCodec { get; private set; }
public bool ExcludeFromGlobalFunctions { get; set; }
public string DefaultSourceItem { get; set; }
public ushort DefaultVolume { get; set; }
/// <summary>
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string LastSourceKey;
/// <summary>
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
/// tag to device.
/// </summary>
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;
/// <summary>
/// "codecOsd"
/// </summary>
public string DefaultCodecRouteString { get { return "codecOsd"; } }
/// <summary>
/// Temporary implementation. Returns the schedule-ready object or null if none. Fow now,
/// always returns the VideoCodec if it is capable
/// </summary>
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
CCriticalSection SourceSelectLock = new CCriticalSection();
public EssentialsDualDisplayRoom(DeviceConfig config)
: base(config)
{
try
{
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsDualDisplayRoomPropertiesConfig>
(config.Properties.ToString());
var leftDisp = PropertiesConfig.Displays[eSourceListItemDestinationTypes.leftDisplay];
if (leftDisp != null)
{
if (!string.IsNullOrEmpty(leftDisp.Key))
{
LeftDisplay = DeviceManager.GetDeviceForKey(leftDisp.Key) as IRoutingSinkWithSwitching;
Displays.Add(eSourceListItemDestinationTypes.leftDisplay, LeftDisplay);
}
else
Debug.Console(0, this, "Unable to get LeftDisplay for Room");
}
var rightDisp = PropertiesConfig.Displays[eSourceListItemDestinationTypes.rightDisplay];
if (rightDisp != null)
{
if (!string.IsNullOrEmpty(rightDisp.Key))
{
LeftDisplay = DeviceManager.GetDeviceForKey(rightDisp.Key) as IRoutingSinkWithSwitching;
Displays.Add(eSourceListItemDestinationTypes.rightDisplay, RightDisplay);
}
else
Debug.Console(0, this, "Unable to get LeftDisplay for Room");
}
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null)
throw new ArgumentNullException("codec cannot be null");
AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null)
Debug.Console(0, this, "No Audio Codec Found");
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls;
InitializeRoom();
}
catch (Exception e)
{
Debug.Console(1, this, "Error building room \n{0}", e);
}
}
void InitializeRoom()
{
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
else if (DefaultAudioDevice is IHasVolumeDevice)
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
var leftDisp = LeftDisplay as DisplayBase;
if (leftDisp != null)
InitializeDisplay(leftDisp);
var rightDisp = RightDisplay as DisplayBase;
if (rightDisp != null)
InitializeDisplay(rightDisp);
// Get Microphone Privacy object, if any
this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
Debug.Console(2, this, "Microphone Privacy Config evaluated.");
// Get emergency object, if any
this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
Debug.Console(2, this, "Emergency Config evaluated.");
// Combines call feedback from both codecs if available
InCallFeedback = new BoolFeedback(() =>
{
bool inAudioCall = false;
bool inVideoCall = false;
if (AudioCodec != null)
inAudioCall = AudioCodec.IsInCall;
if (VideoCodec != null)
inVideoCall = VideoCodec.IsInCall;
if (inAudioCall || inVideoCall)
return true;
else
return false;
});
VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
if (AudioCodec != null)
AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate();
// link privacy to VC (for now?)
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate();
CallTypeFeedback = new IntFeedback(() => 0);
SetSourceListKey();
EnablePowerOnToLastSource = true;
}
private void SetSourceListKey()
{
if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey))
{
SetSourceListKey(PropertiesConfig.SourceListKey);
}
else
{
SetSourceListKey(Key);
}
}
void InitializeDisplay(DisplayBase disp)
{
if (disp != null)
{
// Link power, warming, cooling to display
var dispTwoWay = disp as IHasPowerControlWithFeedback;
if (dispTwoWay != null)
{
dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
disp.CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (dispTwoWay.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
};
}
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
IsWarmingUpFeedback.FireUpdate();
if (!IsWarmingUpFeedback.BoolValue)
(CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
};
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
{
IsCoolingDownFeedback.FireUpdate();
};
}
}
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsDualDisplayRoomPropertiesConfig>(config.Properties.ToString());
if (newPropertiesConfig != null)
PropertiesConfig = newPropertiesConfig;
ConfigWriter.UpdateRoomConfig(config);
}
public override bool CustomActivate()
{
// Add Occupancy object from config
if (PropertiesConfig.Occupancy != null)
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight();
this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark();
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
return base.CustomActivate();
}
/// <summary>
///
/// </summary>
protected override void EndShutdown()
{
VideoCodec.EndAllCalls();
SetDefaultLevels();
RunDefaultPresentRoute();
CrestronEnvironment.Sleep(1000);
RunRouteAction("roomOff", SourceListKey);
}
/// <summary>
/// Routes the default source item, if any. Returns true when default route exists
/// </summary>
public override bool RunDefaultPresentRoute()
{
if (DefaultSourceItem != null)
RunRouteAction(DefaultSourceItem, SourceListKey);
return DefaultSourceItem != null;
}
/// <summary>
/// Sets up the room when started into call mode without presenting a source
/// </summary>
/// <returns></returns>
public bool RunDefaultCallRoute()
{
RunRouteAction(DefaultCodecRouteString, SourceListKey);
return true;
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
public void RunRouteAction(string routeKey, string sourceListKey)
{
RunRouteAction(routeKey, sourceListKey, null);
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback)
{
// Run this on a separate thread
new CTimer(o =>
{
// try to prevent multiple simultaneous selections
SourceSelectLock.TryEnter();
try
{
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;
}
// End usage timer on last source
if (!string.IsNullOrEmpty(LastSourceKey))
{
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
if (usageLastSource != null && usageLastSource.UsageTracker != null)
{
try
{
// There MAY have been failures in here. Protect
usageLastSource.UsageTracker.EndDeviceUsage();
}
catch (Exception e)
{
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking:\r{0}", e);
}
}
}
// Let's run it
var item = dict[routeKey];
if (routeKey.ToLower() != "roomoff")
{
LastSourceKey = routeKey;
}
//else
// CurrentSourceInfoKey = null;
// hand off the individual routes to this helper
foreach (var route in item.RouteList)
DoRouteItem(route, item, routeKey);
// Start usage timer on routed source
var usageNewSource = item.SourceDevice as IUsageTracking;
if (usageNewSource != null && usageNewSource.UsageTracker != null) // Have to make sure there is a usage tracker!
{
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
}
// See if this can be moved into common, base-class method -------------
// Set volume control, 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;
// 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;
}
if (volDev != CurrentVolumeControls)
{
// zero the volume on the device we are leaving.
// Set the volume to default on device we are entering
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
vd.SetVolume(0);
}
CurrentVolumeControls = volDev;
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
vd.SetVolume(vol);
}
}
// -----------------------------------------------------------------------
// store the name and UI info for routes
if (item.SourceKey == "$off")
{
LeftDisplay.CurrentSourceInfoKey = routeKey;
LeftDisplay.CurrentSourceInfo = null;
RightDisplay.CurrentSourceInfoKey = routeKey;
RightDisplay.CurrentSourceInfo = null;
}
//else if (item.SourceKey != null)
//{
// if(item.RouteList
// CurrentSourceInfoKey = routeKey;
// CurrentSourceInfo = item;
//}
OnFeedback.FireUpdate();
// report back when done
if (successCallback != null)
successCallback();
}
catch (Exception e)
{
Debug.Console(1, this, "ERROR in routing: {0}", e);
}
SourceSelectLock.Leave();
}, 0); // end of CTimer
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
void DoRouteItem(SourceRouteListItem route, SourceListItem sourceItem, string sourceItemKey)
{
// 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, sourceItem, sourceItemKey);
}
else
DoRoute(route, sourceItem, sourceItemKey);
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
bool DoRoute(SourceRouteListItem route, SourceListItem sourceItem, string sourceItemKey)
{
IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice as IRoutingSinkNoSwitching;
else if (route.DestinationKey.Equals(LeftDisplay.Key, StringComparison.OrdinalIgnoreCase))
dest = LeftDisplay;
else if (route.DestinationKey.Equals(RightDisplay.Key, StringComparison.OrdinalIgnoreCase))
dest = RightDisplay;
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 IHasPowerControl)
(dest as IHasPowerControl).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);
dest.CurrentSourceInfoKey = sourceItemKey;
dest.CurrentSourceInfo = sourceItem;
}
return true;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//Implement this
}
/// <summary>
/// Does what it says
/// </summary>
public override void SetDefaultLevels()
{
Debug.Console(1, this, "Restoring default levels");
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (vc != null)
vc.SetVolume(DefaultVolume);
}
/// <summary>
/// Will power the room on with the last-used source
/// </summary>
public override void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(LastSourceKey, SourceListKey);
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
/// </summary>
public static void AllRoomsOff()
{
var allRooms = DeviceManager.AllDevices.Where(d =>
d is IEssentialsHuddleSpaceRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
(room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff", (room as IEssentialsHuddleSpaceRoom).SourceListKey);
}
#region IPrivacy Members
public void PrivacyModeOff()
{
VideoCodec.PrivacyModeOff();
}
public void PrivacyModeOn()
{
VideoCodec.PrivacyModeOn();
}
public void PrivacyModeToggle()
{
VideoCodec.PrivacyModeToggle();
}
#endregion
}
}

View File

@@ -1,566 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IEssentialsHuddleSpaceRoom
{
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSourceChange;
protected override Func<bool> OnFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
var val = CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route
&& disp != null;
//&& disp.PowerIsOnFeedback.BoolValue;
return val;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
return disp.IsWarmingUpFeedback.BoolValue;
else
return false;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
return disp.IsCoolingDownFeedback.BoolValue;
else
return false;
};
}
}
public EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; private set; }
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
public IRoutingSink DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
public bool ExcludeFromGlobalFunctions { get; set; }
public string DefaultSourceItem { get; set; }
public ushort DefaultVolume { get; set; }
/// <summary>
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string LastSourceKey;
/// <summary>
///
/// </summary>
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;
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _CurrentSourceInfo; }
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
// 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(_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( _CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
public string CurrentSourceInfoKey { get; set; }
public EssentialsHuddleSpaceRoom(DeviceConfig config)
: base(config)
{
try
{
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleRoomPropertiesConfig>
(config.Properties.ToString());
DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IRoutingSinkWithSwitching;
InitializeRoom();
}
catch (Exception e)
{
Debug.Console(1, this, "Error building room: \n{0}", e);
}
}
void InitializeRoom()
{
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
else if (DefaultAudioDevice is IHasVolumeDevice)
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
{
// Link power, warming, cooling to display
var dispTwoWay = disp as IHasPowerControlWithFeedback;
if (dispTwoWay != null)
{
dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
if (!dispTwoWay.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();
};
}
SetupEnvironmentalControlDevices();
SetSourceListKey();
EnablePowerOnToLastSource = true;
}
private void SetupEnvironmentalControlDevices()
{
if (PropertiesConfig.Environment != null)
{
if (PropertiesConfig.Environment.Enabled)
{
foreach (var d in PropertiesConfig.Environment.DeviceKeys)
{
var envDevice = DeviceManager.GetDeviceForKey(d) as EssentialsDevice;
EnvironmentalControlDevices.Add(envDevice);
}
}
}
}
private void SetSourceListKey()
{
if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey))
{
SetSourceListKey(PropertiesConfig.SourceListKey);
}
else
{
SetSourceListKey(Key);
}
}
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleRoomPropertiesConfig>(config.Properties.ToString());
if (newPropertiesConfig != null)
PropertiesConfig = newPropertiesConfig;
ConfigWriter.UpdateRoomConfig(config);
}
/// <summary>
///
/// </summary>
protected override void EndShutdown()
{
SetDefaultLevels();
RunDefaultPresentRoute();
CrestronEnvironment.Sleep(1000);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
RunRouteAction("roomOff");
}
/// <summary>
/// Routes the default source item, if any
/// </summary>
public override bool RunDefaultPresentRoute()
{
if (DefaultSourceItem == null)
{
Debug.Console(0, this, "Unable to run default present route, DefaultSourceItem is null.");
return false;
}
RunRouteAction(DefaultSourceItem);
return true;
}
public override bool CustomActivate()
{
// Add Occupancy object from config
if (PropertiesConfig.Occupancy != null)
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight();
this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark();
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
return base.CustomActivate();
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
public void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, new Action(() => { }));
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey)
{
RunRouteAction(routeKey, new Action(() => { }));
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback)
{
if (string.IsNullOrEmpty(sourceListKey))
{
RunRouteAction(routeKey, successCallback);
}
else
throw new NotImplementedException();
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, Action successCallback)
{
// Run this on a separate thread
new CTimer(o =>
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "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, 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;
}
if (volDev != CurrentVolumeControls)
{
// zero the volume on the device we are leaving.
// Set the volume to default on device we are entering
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
vd.SetVolume(0);
}
CurrentVolumeControls = volDev;
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
vd.SetVolume(vol);
}
}
// 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
}
/// <summary>
/// Will power the room on with the last-used source
/// </summary>
public override void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(LastSourceKey);
}
/// <summary>
/// Does what it says
/// </summary>
public override void SetDefaultLevels()
{
Debug.Console(1, this, "Restoring default levels");
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (vc != null)
vc.SetVolume(DefaultVolume);
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
bool DoRoute(SourceRouteListItem route)
{
IRoutingSink 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 IRoutingSink;
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 IHasPowerControl)
(dest as IHasPowerControl).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;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//Implement this
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
/// </summary>
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");
}
}
}

View File

@@ -1,948 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials
{
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IEssentialsHuddleVtc1Room
{
private IEssentialsRoomCombiner _roomCombiner;
private bool _codecExternalSourceChange;
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSourceChange;
//************************
// Call-related stuff
public BoolFeedback InCallFeedback { get; private set; }
///// <summary>
///// Make this more specific
///// </summary>
//public List<CodecActiveCallItem> ActiveCalls { get; private set; }
/// <summary>
/// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis
/// </summary>
public IntFeedback CallTypeFeedback { get; private set; }
/// <summary>
///
/// </summary>
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
/// <summary>
/// When something in the room is sharing with the far end or through other means
/// </summary>
public BoolFeedback IsSharingFeedback { get; private set; }
//************************
protected override Func<bool> OnFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
var val = CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route
&& disp != null;
//&& disp.PowerIsOnFeedback.BoolValue;
return val;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
return disp.IsWarmingUpFeedback.BoolValue;
else
return false;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () =>
{
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
return disp.IsCoolingDownFeedback.BoolValue;
else
return false;
};
}
}
public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; }
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
public VideoCodecBase VideoCodec { get; private set; }
public AudioCodecBase AudioCodec { get; private set; }
public bool ExcludeFromGlobalFunctions { get; set; }
public string DefaultSourceItem { get; set; }
public ushort DefaultVolume { get; set; }
/// <summary>
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string LastSourceKey;
/// <summary>
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
/// tag to device.
/// </summary>
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;
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _CurrentSourceInfo; }
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
// 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(_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(_CurrentSourceInfo, ChangeType.DidChange);
var vc = VideoCodec as IHasExternalSourceSwitching;
if (vc != null && !_codecExternalSourceChange)
{
vc.SetSelectedSource(CurrentSourceInfoKey);
}
_codecExternalSourceChange = false;
}
}
SourceListItem _CurrentSourceInfo;
public string CurrentSourceInfoKey { get; set; }
/// <summary>
/// "codecOsd"
/// </summary>
public string DefaultCodecRouteString { get { return "codecOsd"; } }
/// <summary>
/// Temporary implementation. Returns the schedule-ready object or null if none. Fow now,
/// always returns the VideoCodec if it is capable
/// </summary>
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
CCriticalSection SourceSelectLock = new CCriticalSection();
public EssentialsHuddleVtc1Room(DeviceConfig config)
: base(config)
{
try
{
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
(config.Properties.ToString());
DefaultDisplay = DeviceManager.GetDeviceForKey((PropertiesConfig as EssentialsHuddleVtc1PropertiesConfig).DefaultDisplayKey) as IRoutingSinkWithSwitching;
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "No Video Codec set. Please check 'videoCodecKey' property in room config");
throw new ArgumentNullException("VideoCodec cannot be null");
}
AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null)
Debug.Console(0, this, "No Audio Codec Found");
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls;
if (DefaultAudioDevice == null)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "No Default Audio Device set. Please check 'defaultAudioKey' property in room config");
throw new ArgumentNullException("DefaultAudioDevice cannot be null");
}
Initialize();
}
catch (Exception e)
{
Debug.Console(1, this, "Error building room: \n{0}", e);
}
}
private void SetupEnvironmentalControlDevices()
{
if (PropertiesConfig.Environment != null)
{
if (PropertiesConfig.Environment.Enabled)
{
EnvironmentalControlDevices.Clear();
foreach (var d in PropertiesConfig.Environment.DeviceKeys)
{
var envDevice = DeviceManager.GetDeviceForKey(d) as EssentialsDevice;
EnvironmentalControlDevices.Add(envDevice);
}
}
}
}
private void SetSourceListKey()
{
if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey))
{
SetSourceListKey(PropertiesConfig.SourceListKey);
}
else
{
SetSourceListKey(Key);
}
SetUpVideoCodec();
}
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>(config.Properties.ToString());
if (newPropertiesConfig != null)
PropertiesConfig = newPropertiesConfig;
ConfigWriter.UpdateRoomConfig(config);
}
public override bool Deactivate()
{
// Stop listining to this event when room deactivated
VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange;
// Clear occupancy
RoomOccupancy = null;
Debug.Console(0, this, "Room '{0}' Deactivated", Name);
return base.Deactivate();
}
public override bool CustomActivate()
{
try
{
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
else if (DefaultAudioDevice is IHasVolumeDevice)
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
// Combines call feedback from both codecs if available
InCallFeedback = new BoolFeedback(() =>
{
bool inAudioCall = false;
bool inVideoCall = false;
if (AudioCodec != null)
inAudioCall = AudioCodec.IsInCall;
if (VideoCodec != null)
inVideoCall = VideoCodec.IsInCall;
if (inAudioCall || inVideoCall)
return true;
else
return false;
});
var disp = DefaultDisplay as DisplayBase;
if (disp != null)
{
// Link power, warming, cooling to display
var dispTwoWay = disp as IHasPowerControlWithFeedback;
if (dispTwoWay != null)
{
dispTwoWay.PowerIsOnFeedback.OutputChange -= PowerIsOnFeedback_OutputChange;
dispTwoWay.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
}
disp.IsWarmingUpFeedback.OutputChange -= IsWarmingUpFeedback_OutputChange;
disp.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
disp.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange;
disp.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
}
// Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback
this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
Debug.Console(2, this, "Microphone Privacy Config evaluated.");
// Get emergency object, if any
this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
Debug.Console(2, this, "Emergency Config evaluated.");
if (AudioCodec != null)
{
AudioCodec.CallStatusChange -= AudioCodec_CallStatusChange;
AudioCodec.CallStatusChange += AudioCodec_CallStatusChange;
}
VideoCodec.CallStatusChange -= VideoCodec_CallStatusChange;
VideoCodec.CallStatusChange += VideoCodec_CallStatusChange;
VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange;
VideoCodec.IsReadyChange += VideoCodec_IsReadyChange;
VideoCodec.SharingContentIsOnFeedback.OutputChange -= SharingContentIsOnFeedback_OutputChange;
VideoCodec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange;
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
// link privacy to VC (for now?)
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
VideoCodec.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange;
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange;
CallTypeFeedback = new IntFeedback(() => 0);
SetupEnvironmentalControlDevices();
SetSourceListKey();
EnablePowerOnToLastSource = true;
// Add Occupancy object from config
if (PropertiesConfig.Occupancy != null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room");
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
}
this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight();
this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark();
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
}
catch (Exception e)
{
Debug.Console(0, this, "Error Activiating Room: {0}", e);
}
Debug.Console(0, this, "Room '{0}' Activated", Name);
return base.CustomActivate();
}
void PrivacyModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PrivacyModeIsOnFeedback.FireUpdate();
}
void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
IsSharingFeedback.FireUpdate();
}
void AudioCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
InCallFeedback.FireUpdate();
}
void VideoCodec_IsReadyChange(object sender, EventArgs e)
{
SetUpVideoCodec();
}
void SetUpVideoCodec()
{
SetCodecExternalSources();
SetCodecBranding();
}
void VideoCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
InCallFeedback.FireUpdate();
}
void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
IsCoolingDownFeedback.FireUpdate();
}
void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
IsWarmingUpFeedback.FireUpdate();
if (!IsWarmingUpFeedback.BoolValue)
(CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
}
void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var dispTwoWay = DefaultDisplay as IHasPowerControlWithFeedback;
if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (dispTwoWay.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
}
/// <summary>
///
/// </summary>
protected override void EndShutdown()
{
VideoCodec.EndAllCalls();
SetDefaultLevels();
RunDefaultPresentRoute();
CrestronEnvironment.Sleep(1000);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
RunRouteAction("roomOff");
VideoCodec.StopSharing();
VideoCodec.StandbyActivate();
}
/// <summary>
/// Routes the default source item, if any. Returns true when default route exists
/// </summary>
public override bool RunDefaultPresentRoute()
{
if (DefaultSourceItem != null)
RunRouteAction(DefaultSourceItem);
return DefaultSourceItem != null;
}
/// <summary>
/// Sets up the room when started into call mode without presenting a source
/// </summary>
/// <returns></returns>
public bool RunDefaultCallRoute()
{
Debug.Console(2, this, "RunDefaultCallRoute() Currently Sharing Content: {0}", VideoCodec.SharingContentIsOnFeedback.BoolValue);
if (VideoCodec.SharingContentIsOnFeedback.BoolValue)
{
Debug.Console(2, this, "Currently sharing content. Ignoring request to run default call route.");
return false;
}
RunRouteAction(DefaultCodecRouteString);
return true;
}
public void RunRouteActionCodec(string routeKey, string sourceListKey)
{
_codecExternalSourceChange = true;
RunRouteAction(routeKey, sourceListKey);
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
public void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, new Action(() => { }));
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey)
{
if (string.IsNullOrEmpty(sourceListKey))
{
Debug.Console(1, this, "No sourceListKey present. RunRouteAction assumes default source list.");
RunRouteAction(routeKey, new Action(() => { }));
}
else
{
Debug.Console(1, this, "sourceListKey present but not yet implemented");
RunRouteAction(routeKey, new Action(() => { }));
}
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback)
{
if (string.IsNullOrEmpty(sourceListKey))
{
RunRouteAction(routeKey, successCallback);
}
else
{
Debug.Console(1, this, "sourceListKey present but not yet implemented");
RunRouteAction(routeKey, successCallback);
}
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, Action successCallback)
{
// Run this on a separate thread
new CTimer(o =>
{
// try to prevent multiple simultaneous selections
SourceSelectLock.TryEnter();
try
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "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;
}
// End usage timer on last source
if (!string.IsNullOrEmpty(LastSourceKey))
{
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
if (usageLastSource != null && usageLastSource.UsageTracker != null)
{
try
{
// There MAY have been failures in here. Protect
usageLastSource.UsageTracker.EndDeviceUsage();
}
catch (Exception e)
{
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking:\r{0}", e);
}
}
}
// Let's run it
var item = dict[routeKey];
if (routeKey.ToLower() != "roomoff")
{
LastSourceKey = routeKey;
}
else
CurrentSourceInfoKey = null;
// hand off the individual routes to this helper
foreach (var route in item.RouteList)
DoRouteItem(route);
// Start usage timer on routed source
var usageNewSource = item.SourceDevice as IUsageTracking;
if (usageNewSource != null && usageNewSource.UsageTracker != null) // Have to make sure there is a usage tracker!
{
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
}
// See if this can be moved into common, base-class method -------------
// Set volume control, 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;
}
if (volDev != CurrentVolumeControls)
{
// zero the volume on the device we are leaving.
// Set the volume to default on device we are entering
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
vd.SetVolume(0);
}
CurrentVolumeControls = volDev;
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
vd.SetVolume(vol);
}
}
// -----------------------------------------------------------------------
// 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();
if (OnFeedback.BoolValue)
{
if (VideoCodec.UsageTracker.InUseTracker.InUseFeedback.BoolValue)
{
Debug.Console(1, this, "Video Codec in use, deactivating standby on codec");
VideoCodec.StandbyDeactivate();
}
if (VideoCodec.StandbyIsOnFeedback.BoolValue)
{
VideoCodec.StandbyDeactivate();
}
else
{
Debug.Console(1, this, "Video codec not in standby. No need to wake.");
}
}
else
{
Debug.Console(1, this, "Room OnFeedback state: {0}", OnFeedback.BoolValue);
}
// report back when done
if (successCallback != null)
successCallback();
}
catch (Exception e)
{
Debug.Console(1, this, "ERROR in routing: {0}", e);
}
SourceSelectLock.Leave();
}, 0); // end of CTimer
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
void DoRouteItem(SourceRouteListItem route)
{
// 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);
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
bool DoRoute(SourceRouteListItem route)
{
IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice as IRoutingSink;
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
dest = DefaultDisplay;
else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
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 IHasPowerControl)
(dest as IHasPowerControl).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;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//Implement this
}
protected override bool AllowVacancyTimerToStart()
{
bool allowVideo = true;
bool allowAudio = true;
if (VideoCodec != null)
{
Debug.Console(2,this, Debug.ErrorLogLevel.Notice, "Room {0} {1} in a video call", Key, VideoCodec.IsInCall ? "is" : "is not");
allowVideo = !VideoCodec.IsInCall;
}
if (AudioCodec != null)
{
Debug.Console(2,this, Debug.ErrorLogLevel.Notice, "Room {0} {1} in an audio call", Key, AudioCodec.IsInCall ? "is" : "is not");
allowAudio = !AudioCodec.IsInCall;
}
Debug.Console(2, this, "Room {0} allowing vacancy timer to start: {1}", Key, allowVideo && allowAudio);
return allowVideo && allowAudio;
}
/// <summary>
/// Does what it says
/// </summary>
public override void SetDefaultLevels()
{
Debug.Console(1, this, "Restoring default levels");
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (vc != null)
vc.SetVolume(DefaultVolume);
}
/// <summary>
/// Will power the room on with the last-used source
/// </summary>
public override void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(LastSourceKey);
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
/// </summary>
public static void AllRoomsOff()
{
var allRooms = DeviceManager.AllDevices.Where(d =>
d is IEssentialsRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
(room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
}
/// <summary>
/// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
/// </summary>
private void SetCodecExternalSources()
{
var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
if (videoCodecWithExternalSwitching == null || !videoCodecWithExternalSwitching.ExternalSourceListEnabled)
{
return;
}
try
{
// Get the tie line that the external switcher is connected to
string codecInputConnectorName = ConfigReader.ConfigObject.TieLines.SingleOrDefault(
x => x.DestinationKey == VideoCodec.Key && x.DestinationPort == videoCodecWithExternalSwitching.ExternalSourceInputPort).DestinationPort;
videoCodecWithExternalSwitching.ClearExternalSources();
videoCodecWithExternalSwitching.RunRouteAction = RunRouteActionCodec;
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
foreach (var kvp in srcList)
{
var srcConfig = kvp.Value;
if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff")
{
videoCodecWithExternalSwitching.AddExternalSource(codecInputConnectorName, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop);
videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready);
}
}
Debug.Console(1, this, "Successfully set up codec external sources for room: {0}", Name);
}
catch (Exception e)
{
Debug.Console(2, this, "Error setting codec external sources: {0}", e);
}
}
private void SetCodecBranding()
{
var vcWithBranding = VideoCodec as IHasBranding;
if (vcWithBranding == null) return;
Debug.Console(1, this, "Setting Codec Branding");
vcWithBranding.InitializeBranding(Key);
}
#region IPrivacy Members
public void PrivacyModeOff()
{
VideoCodec.PrivacyModeOff();
}
public void PrivacyModeOn()
{
VideoCodec.PrivacyModeOn();
}
public void PrivacyModeToggle()
{
VideoCodec.PrivacyModeToggle();
}
#endregion
}
}

View File

@@ -1,35 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Full.Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
/// <summary>
/// Base class for rooms with more than a single display
/// </summary>
public abstract class EssentialsNDisplayRoomBase : EssentialsRoomBase, IHasMultipleDisplays
{
//public event SourceInfoChangeHandler CurrentSingleSourceChange;
public Dictionary<eSourceListItemDestinationTypes, IRoutingSinkWithSwitching> Displays { get; protected set;}
public EssentialsNDisplayRoomBase(DeviceConfig config)
: base (config)
{
Displays = new Dictionary<eSourceListItemDestinationTypes, IRoutingSinkWithSwitching>();
}
}
}

View File

@@ -1,519 +0,0 @@
extern alias Full;
using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler;
using Crestron.SimplSharpPro.DeviceSupport;
using Full.Newtonsoft.Json;
using Full.Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Presets;
using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public class EssentialsTechRoom : EssentialsRoomBase, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction
{
public EssentialsTechRoomConfig PropertiesConfig { get; private set; }
private readonly Dictionary<string, TwoWayDisplayBase> _displays;
private readonly DevicePresetsModel _tunerPresets;
private readonly Dictionary<string, IRSetTopBoxBase> _tuners;
private Dictionary<string, string> _currentPresets;
private ScheduledEventGroup _roomScheduledEventGroup;
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () =>
{
return _displays.All(kv => kv.Value.IsWarmingUpFeedback.BoolValue);
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () =>
{
return _displays.All(kv => kv.Value.IsCoolingDownFeedback.BoolValue);
};
}
}
public EssentialsTechRoom(DeviceConfig config) : base(config)
{
PropertiesConfig = config.Properties.ToObject<EssentialsTechRoomConfig>();
_tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), PropertiesConfig.PresetsFileName);
_tunerPresets.SetFileName(PropertiesConfig.PresetsFileName);
_tunerPresets.PresetRecalled += TunerPresetsOnPresetRecalled;
_tuners = GetDevices<IRSetTopBoxBase>(PropertiesConfig.Tuners);
_displays = GetDevices<TwoWayDisplayBase>(PropertiesConfig.Displays);
RoomPowerIsOnFeedback = new BoolFeedback(() => RoomPowerIsOn);
SetUpTunerPresetsFeedback();
SubscribeToDisplayFeedbacks();
CreateOrUpdateScheduledEvents();
}
public Dictionary<string, StringFeedback> CurrentPresetsFeedbacks { get; private set; }
public Dictionary<string, IRSetTopBoxBase> Tuners
{
get { return _tuners; }
}
public Dictionary<string, TwoWayDisplayBase> Displays
{
get { return _displays; }
}
public BoolFeedback RoomPowerIsOnFeedback { get; private set; }
public bool RoomPowerIsOn
{
get { return _displays.All(kv => kv.Value.PowerIsOnFeedback.BoolValue); }
}
#region ITvPresetsProvider Members
public DevicePresetsModel TvPresets
{
get { return _tunerPresets; }
}
#endregion
private void TunerPresetsOnPresetRecalled(ISetTopBoxNumericKeypad device, string channel)
{
//Debug.Console(2, this, "TunerPresetsOnPresetRecalled");
if (!_currentPresets.ContainsKey(device.Key))
{
return;
}
//Debug.Console(2, this, "Tuner Key: {0} Channel: {1}", device.Key, channel);
_currentPresets[device.Key] = channel;
if (CurrentPresetsFeedbacks.ContainsKey(device.Key))
{
CurrentPresetsFeedbacks[device.Key].FireUpdate();
}
}
private void SetUpTunerPresetsFeedback()
{
_currentPresets = new Dictionary<string, string>();
CurrentPresetsFeedbacks = new Dictionary<string, StringFeedback>();
foreach (var setTopBox in _tuners)
{
var tuner = setTopBox.Value;
_currentPresets.Add(tuner.Key, String.Empty);
CurrentPresetsFeedbacks.Add(tuner.Key, new StringFeedback(() => _currentPresets[tuner.Key]));
}
}
private void SubscribeToDisplayFeedbacks()
{
foreach (var display in _displays)
{
display.Value.PowerIsOnFeedback.OutputChange +=
(sender, args) =>
{
RoomPowerIsOnFeedback.InvokeFireUpdate();
IsWarmingUpFeedback.InvokeFireUpdate();
IsCoolingDownFeedback.InvokeFireUpdate();
};
}
}
private void CreateOrUpdateScheduledEvents()
{
var eventsConfig = PropertiesConfig.ScheduledEvents;
GetOrCreateScheduleGroup();
foreach (var eventConfig in eventsConfig)
{
CreateOrUpdateSingleEvent(eventConfig);
}
_roomScheduledEventGroup.UserGroupCallBack += HandleScheduledEvent;
}
private void GetOrCreateScheduleGroup()
{
if (_roomScheduledEventGroup == null)
{
_roomScheduledEventGroup = Scheduler.GetEventGroup(Key) ?? new ScheduledEventGroup(Key);
Scheduler.AddEventGroup(_roomScheduledEventGroup);
}
_roomScheduledEventGroup.RetrieveAllEvents();
}
private void CreateOrUpdateSingleEvent(ScheduledEventConfig scheduledEvent)
{
if (!_roomScheduledEventGroup.ScheduledEvents.ContainsKey(scheduledEvent.Key))
{
SchedulerUtilities.CreateEventFromConfig(scheduledEvent, _roomScheduledEventGroup, HandleScheduledEvent);
return;
}
var roomEvent = _roomScheduledEventGroup.ScheduledEvents[scheduledEvent.Key];
//if (SchedulerUtilities.CheckEventTimeForMatch(roomEvent, DateTime.Parse(scheduledEvent.Time)) &&
// SchedulerUtilities.CheckEventRecurrenceForMatch(roomEvent, scheduledEvent.Days))
//{
// Debug.Console(1, this, "Existing event matches new event properties. Nothing to update");
// return;
//}
Debug.Console(1, this,
"Existing event does not match new config properties. Deleting existing event '{0}' and creating new event from configuration",
roomEvent.Name);
_roomScheduledEventGroup.DeleteEvent(roomEvent);
SchedulerUtilities.CreateEventFromConfig(scheduledEvent, _roomScheduledEventGroup, HandleScheduledEvent);
}
public void AddOrUpdateScheduledEvent(ScheduledEventConfig scheduledEvent)
{
//update config based on key of scheduleEvent
GetOrCreateScheduleGroup();
var existingEventIndex = PropertiesConfig.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key);
if (existingEventIndex < 0)
{
PropertiesConfig.ScheduledEvents.Add(scheduledEvent);
}
else
{
PropertiesConfig.ScheduledEvents[existingEventIndex] = scheduledEvent;
}
//create or update event based on config
CreateOrUpdateSingleEvent(scheduledEvent);
//save config
Config.Properties = JToken.FromObject(PropertiesConfig);
CustomSetConfig(Config);
//Fire Event
OnScheduledEventUpdate();
}
public List<ScheduledEventConfig> GetScheduledEvents()
{
return PropertiesConfig.ScheduledEvents ?? new List<ScheduledEventConfig>();
}
private void OnScheduledEventUpdate()
{
var handler = ScheduledEventsChanged;
if (handler == null)
{
return;
}
handler(this, new ScheduledEventEventArgs {ScheduledEvents = PropertiesConfig.ScheduledEvents});
}
public event EventHandler<ScheduledEventEventArgs> ScheduledEventsChanged;
private void HandleScheduledEvent(ScheduledEvent schevent, ScheduledEventCommon.eCallbackReason type)
{
var eventConfig = PropertiesConfig.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name);
if (eventConfig == null)
{
Debug.Console(1, this, "Event with name {0} not found", schevent.Name);
return;
}
Debug.Console(1, this, "Running actions for event {0}", schevent.Name);
if (eventConfig.Acknowledgeable)
{
schevent.Acknowledge();
}
CrestronInvoke.BeginInvoke((o) =>
{
Debug.Console(2, this, "There are {0} actions to execute for this event.", eventConfig.Actions.Count);
foreach (var a in eventConfig.Actions)
{
Debug.Console(2, this,
@"Attempting to run action:
Key: {0}
MethodName: {1}
Params: {2}"
, a.DeviceKey, a.MethodName, a.Params);
DeviceJsonApi.DoDeviceAction(a);
}
});
}
public void RoomPowerOn()
{
Debug.Console(2, this, "Room Powering On");
var dummySource = DeviceManager.GetDeviceForKey(PropertiesConfig.DummySourceKey) as IRoutingOutputs;
if (dummySource == null)
{
Debug.Console(1, this, "Unable to get source with key: {0}", PropertiesConfig.DummySourceKey);
return;
}
foreach (var display in _displays)
{
RunDirectRoute(dummySource, display.Value);
}
}
public void RoomPowerOff()
{
Debug.Console(2, this, "Room Powering Off");
foreach (var display in _displays)
{
display.Value.PowerOff();
}
}
private Dictionary<string, T> GetDevices<T>(ICollection<string> config) where T : IKeyed
{
try
{
var returnValue = DeviceManager.AllDevices.OfType<T>()
.Where(d => config.Contains(d.Key))
.ToDictionary(d => d.Key, d => d);
return returnValue;
}
catch
{
Debug.Console(0, this, Debug.ErrorLogLevel.Error,
"Error getting devices. Check Essentials Configuration");
return null;
}
}
#region Overrides of EssentialsRoomBase
protected override Func<bool> OnFeedbackFunc
{
get { return () => RoomPowerIsOn; }
}
protected override void EndShutdown()
{
}
public override void SetDefaultLevels()
{
}
public override void PowerOnToDefaultOrLastSource()
{
}
public override bool RunDefaultPresentRoute()
{
return false;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
}
#endregion
#region Implementation of IBridgeAdvanced
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new EssentialsTechRoomJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!String.IsNullOrEmpty(joinMapSerialized))
{
joinMap = JsonConvert.DeserializeObject<EssentialsTechRoomJoinMap>(joinMapSerialized);
}
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
if (PropertiesConfig.IsPrimary)
{
Debug.Console(1, this, "Linking Primary system Tuner Preset Mirroring");
if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0)
{
foreach (var tuner in PropertiesConfig.MirroredTuners)
{
var f = CurrentPresetsFeedbacks[tuner.Value];
if (f == null)
{
Debug.Console(1, this, "Unable to find feedback with key: {0}", tuner.Value);
continue;
}
var join = joinMap.CurrentPreset.JoinNumber + tuner.Key;
f.LinkInputSig(trilist.StringInput[(uint)(join)]);
Debug.Console(1, this, "Linked Current Preset feedback for tuner: {0} to serial join: {1}", tuner.Value, join);
}
}
//i = 0;
//foreach (var feedback in CurrentPresetsFeedbacks)
//{
// feedback.Value.LinkInputSig(trilist.StringInput[(uint) (joinMap.CurrentPreset.JoinNumber + i)]);
// i++;
//}
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine)
{
return;
}
foreach (var feedback in CurrentPresetsFeedbacks)
{
feedback.Value.FireUpdate();
}
};
return;
}
else
{
Debug.Console(1, this, "Linking Secondary system Tuner Preset Mirroring");
if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0)
{
foreach (var tuner in PropertiesConfig.MirroredTuners)
{
var t = _tuners[tuner.Value];
if (t == null)
{
Debug.Console(1, this, "Unable to find tuner with key: {0}", tuner.Value);
continue;
}
var join = joinMap.CurrentPreset.JoinNumber + tuner.Key;
trilist.SetStringSigAction(join, s => _tunerPresets.Dial(s, t));
Debug.Console(1, this, "Linked preset recall action for tuner: {0} to serial join: {1}", tuner.Value, join);
}
//foreach (var setTopBox in _tuners)
//{
// var tuner = setTopBox;
// trilist.SetStringSigAction(joinMap.CurrentPreset.JoinNumber + i, s => _tunerPresets.Dial(s, tuner.Value));
//}
}
}
}
#endregion
private class EssentialsTechRoomJoinMap : JoinMapBaseAdvanced
{
[JoinName("currentPreset")]
public JoinDataComplete CurrentPreset = new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 16},
new JoinMetadata {Description = "Current Tuner Preset", JoinType = eJoinType.Serial});
public EssentialsTechRoomJoinMap(uint joinStart) : base(joinStart, typeof(EssentialsTechRoomJoinMap))
{
}
}
#region IRunDirectRouteAction Members
private void RunDirectRoute(IRoutingOutputs source, IRoutingSink dest)
{
if (dest == null)
{
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", dest.Key);
return;
}
if (source == null)
{
dest.ReleaseRoute();
if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff();
}
else
{
dest.ReleaseAndMakeRoute(source, eRoutingSignalType.Video);
}
}
/// <summary>
/// Attempts to route directly between a source and destination
/// </summary>
/// <param name="sourceKey"></param>
/// <param name="destinationKey"></param>
public void RunDirectRoute(string sourceKey, string destinationKey)
{
IRoutingSink dest = null;
dest = DeviceManager.GetDeviceForKey(destinationKey) as IRoutingSink;
var source = DeviceManager.GetDeviceForKey(sourceKey) as IRoutingOutputs;
if (source == null || dest == null)
{
Debug.Console(1, this, "Cannot route unknown source or destination '{0}' to {1}", sourceKey, destinationKey);
return;
}
RunDirectRoute(source, dest);
}
#endregion
}
public class ScheduledEventEventArgs : EventArgs
{
public List<ScheduledEventConfig> ScheduledEvents;
}
}

View File

@@ -1,25 +0,0 @@
using System;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls, IRoomOccupancy,
IEmergency, IMicrophonePrivacy
{
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; }
IBasicVolumeControls CurrentVolumeControls { get; }
event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
}
}

View File

@@ -1,28 +0,0 @@
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange,
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback,
IRoomOccupancy, IEmergency, IMicrophonePrivacy
{
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
IHasScheduleAwareness ScheduleSource { get; }
new BoolFeedback InCallFeedback { get; }
new BoolFeedback PrivacyModeIsOnFeedback { get; }
string DefaultCodecRouteString { get; }
}
}

View File

@@ -1,28 +0,0 @@
//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<bool>(routeAction);
// }
// }
// }
//}

View File

@@ -1,290 +0,0 @@
extern alias Full;
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.Config;
using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.Core.UI;
using Full.Newtonsoft.Json;
namespace PepperDash.Essentials
{
public class EssentialsTouchpanelController : TouchpanelBase
{
public PanelDriverBase PanelDriver { get; private set; }
CTimer BacklightTransitionedOnTimer;
/// <summary>
/// Config constructor
/// </summary>
public EssentialsTouchpanelController(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config)
: base(key, name, panel, config)
{
}
/// <summary>
/// Sets up drivers and links them to the room specified
/// </summary>
/// <param name="roomKey">key of room to link the drivers to</param>
protected override void SetupPanelDrivers(string roomKey)
{
// Clear out any existing actions
Panel.ClearAllSigActions();
Debug.Console(0, this, "Linking TP '{0}' to Room '{1}'", Key, roomKey);
var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, _config);
// Then the sub drivers
// spin up different room drivers depending on room type
var room = DeviceManager.GetDeviceForKey(roomKey);
if (room is IEssentialsHuddleSpaceRoom)
{
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _config);
// Header Driver
Debug.Console(0, this, "Adding header driver");
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _config);
// AV Driver
Debug.Console(0, this, "Adding huddle space AV driver");
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, _config);
avDriver.DefaultRoomKey = roomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, this, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _config);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
}
else if (room is IEssentialsHuddleVtc1Room)
{
Debug.Console(0, this, "Adding huddle space VTC AV driver");
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _config);
// Header Driver
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _config);
// AV Driver
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, _config);
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(Panel, avDriver,
(room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver);
avDriver.SetVideoCodecDriver(codecDriver);
avDriver.DefaultRoomKey = roomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleVtc1Room;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, this, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _config);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.EndMeetingPress(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
LoadAndShowDriver(mainDriver);
}
else
{
Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", roomKey);
}
}
public void LoadAndShowDriver(PanelDriverBase driver)
{
if (PanelDriver != null)
{
var mainDriver = PanelDriver as EssentialsPanelMainInterfaceDriver;
if (mainDriver != null)
{
mainDriver.Dispose();
}
}
PanelDriver = driver;
driver.Show();
}
protected override void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
{
// If the sig is transitioning on, mark it in case it was home button that transitioned it
var blOnSig = (Panel as TswFt5ButtonSystem).ExtenderSystemReservedSigs.BacklightOnFeedback;
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<bool>;
if (act != null)
{
act(true);
act(false);
}
}
public void SetBoolSig(uint join, bool value)
{
var act = Panel.BooleanInput[join].UserObject as Action<bool>;
if (act != null)
act(value);
}
public void SetIntSig(uint join, ushort value)
{
var act = Panel.BooleanInput[join].UserObject as Action<ushort>;
if (act != null)
{
act(value);
}
}
}
public class EssentialsTouchpanelControllerFactory : EssentialsDeviceFactory<EssentialsTouchpanelController>
{
public EssentialsTouchpanelControllerFactory()
{
TypeNames = new List<string>() { "crestronapp", "tsw550", "tsw750", "tsw1050", "tsw560", "tsw760", "tsw1060", "tsw570", "tsw770", "ts770", "tsw1070", "ts1070", "xpanel" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
var comm = CommFactory.GetControlPropertiesConfig(dc);
var props = JsonConvert.DeserializeObject<CrestronTouchpanelPropertiesConfig>(dc.Properties.ToString());
var panel = GetPanelForType(dc.Type, comm.IpIdInt, props.ProjectName);
if (panel == null)
{
Debug.Console(0, "Unable to create Touchpanel for type {0}. Touchpanel Controller WILL NOT function correctly", dc.Type);
}
Debug.Console(1, "Factory Attempting to create new EssentialsTouchpanelController");
var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, panel, props);
return panelController;
}
private BasicTriListWithSmartObject GetPanelForType(string type, uint id, string projectName)
{
type = type.ToLower();
try
{
if (type == "crestronapp")
{
var app = new CrestronApp(id, Global.ControlSystem);
app.ParameterProjectName.Value = projectName;
return app;
}
else if (type == "xpanel")
return new XpanelForSmartGraphics(id, Global.ControlSystem);
else if (type == "tsw550")
return new Tsw550(id, Global.ControlSystem);
else if (type == "tsw552")
return new Tsw552(id, Global.ControlSystem);
else if (type == "tsw560")
return new Tsw560(id, Global.ControlSystem);
else if (type == "tsw750")
return new Tsw750(id, Global.ControlSystem);
else if (type == "tsw752")
return new Tsw752(id, Global.ControlSystem);
else if (type == "tsw760")
return new Tsw760(id, Global.ControlSystem);
else if (type == "tsw1050")
return new Tsw1050(id, Global.ControlSystem);
else if (type == "tsw1052")
return new Tsw1052(id, Global.ControlSystem);
else if (type == "tsw1060")
return new Tsw1060(id, Global.ControlSystem);
else if (type == "tsw570")
return new Tsw570(id, Global.ControlSystem);
else if (type == "tsw770")
return new Tsw770(id, Global.ControlSystem);
else if (type == "ts770")
return new Ts770(id, Global.ControlSystem);
else if (type == "tsw1070")
return new Tsw1070(id, Global.ControlSystem);
else if (type == "ts1070")
return new Ts1070(id, Global.ControlSystem);
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type);
return null;
}
}
catch (Exception e)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
return null;
}
}
}
}

View File

@@ -1,991 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
namespace PepperDash.Essentials
{
/// <summary>
/// Where all UI element common joins are defined
/// </summary>
public class UIBoolJoin
{
/// <summary>
/// 901
/// </summary>
public const uint VolumeUpPress = 901;
/// <summary>
/// 902
/// </summary>
public const uint VolumeDownPress = 902;
//****************************************************
// Codec General
/// <summary>
/// 1001
/// </summary>
public const uint CallEndPress = 1001;
/// <summary>
/// 1002
/// </summary>
public const uint CallEndAllConfirmPress = 1002;
/// <summary>
/// 1003 - For tapping the text field to reveal the keyboard
/// </summary>
public const uint CodecDirectorySearchTextPress = 1003;
/// <summary>
/// 1004
/// </summary>
public const uint CallStopSharingPress = 1004;
/// <summary>
/// 1005
/// </summary>
public const uint CallSharedSourceInfoVisible = 1005;
/// <summary>
/// 1006
/// </summary>
public const uint CallEndAllConfirmVisible = 1006;
/// <summary>
/// 1007
/// </summary>
public const uint MeetingPasswordVisible = 1007;
/// <summary>
/// 1008
/// </summary>
public const uint MeetingLeavePress = 1008;
// Audio Conference
/// <summary>
/// 1101
/// </summary>
public const uint ACKeypadVisible = 1101;
/// <summary>
/// 1102
/// </summary>
public const uint ACStagingPopoverVisible = 1102;
/// <summary>
/// 1111
/// </summary>
public const uint ACSpeedDial1Press = 1111;
/// <summary>
/// 1112
/// </summary>
public const uint ACSpeedDial2Press = 1112;
/// <summary>
/// 1113
/// </summary>
public const uint ACSpeedDial3Press = 1113;
/// <summary>
/// 1114
/// </summary>
public const uint ACSpeedDial4Press = 1114;
/// <summary>
/// 1121
/// </summary>
public const uint ACSpeedDial1Visible = 1121;
/// <summary>
/// 1122
/// </summary>
public const uint ACSpeedDial2Visible = 1122;
/// <summary>
/// 1123
/// </summary>
public const uint ACSpeedDial3Visible = 1123;
/// <summary>
/// 1124
/// </summary>
public const uint ACSpeedDial4Visible = 1124;
//******************************************************
// Video Conference
/// <summary>
/// 1201
/// </summary>
public const uint VCKeypadWithFavoritesVisible = 1201;
/// <summary>
/// 1202
/// </summary>
public const uint VCStagingInactivePopoverWithRecentsVisible = 1202;
/// <summary>
///
/// </summary>
public const uint VCStagingActivePopoverVisible = 1203;
/// <summary>
///
/// </summary>
public const uint VCKeypadVisible = 1204;
/// <summary>
/// 1205
/// </summary>
public const uint VCDirectoryVisible = 1205;
/// <summary>
/// 1206
/// </summary>
public const uint VCRecentsVisible = 1206;
/// <summary>
/// 1202
/// </summary>
public const uint VCStagingInactivePopoverWithoutRecentsVisible = 1207;
/// <summary>
/// 1208
/// </summary>
public const uint VCCameraAutoVisible = 1208;
/// <summary>
/// 1209
/// </summary>
public const uint VCCameraManualVisible = 1209;
/// <summary>
/// 1210
/// </summary>
public const uint VCCameraOffVisible = 1210;
/// <summary>
/// 1211 - 1215
/// </summary>
public const uint VCFavoritePressStart = 1211;
// RANGE IN USE
public const uint VCFavoritePressEnd = 1215;
/// <summary>
/// 1221 - 1225
/// </summary>
public const uint VCFavoriteVisibleStart = 1221;
// RANGE IN USE
public const uint VCFavoriteVisibleEnd = 1225;
/// <summary>
/// 1230
/// </summary>
public const uint VCStagingMeetNowPress = 1230;
/// <summary>
/// 1231
/// </summary>
public const uint VCStagingRecentsPress = 1231;
/// <summary>
/// 1232
/// </summary>
public const uint VCStagingDirectoryPress = 1232;
/// <summary>
/// 1233
/// </summary>
public const uint VCStagingKeypadPress = 1233;
/// <summary>
/// 1234
/// </summary>
public const uint VCStagingConnectPress = 1234;
/// <summary>
/// 1235
/// </summary>
public const uint VCStagingCameraPress = 1235;
/// <summary>
/// 1236
/// </summary>
public const uint VCStagingConnectEnable = 1236;
/// <summary>
/// 1237 - When the user touches the text field, should trigger keyboard
/// </summary>
public const uint VCKeypadTextPress = 1237;
/// <summary>
/// 1238
/// </summary>
public const uint VCKeypadBackspacePress = 1238;
/// <summary>
/// 1239
/// </summary>
public const uint VCKeypadBackspaceVisible = 1239;
/// <summary>
/// 1240
/// </summary>
public const uint VCDirectoryBackPress = 1240;
/// <summary>
/// 1241 For touching the text area to bring up keyboard
/// </summary>
public const uint VCDirectorySearchTextPress = 1241;
/// <summary>
/// 1242
/// </summary>
public const uint VCStagingSelfViewLayoutPress = 1242;
/// <summary>
/// 1243
/// </summary>
public const uint VCDirectoryBackVisible = 1243;
/// <summary>
/// 1244
/// </summary>
public const uint VCDirectoryBackspacePress = 1244;
/// <summary>
/// 1245
/// </summary>
public const uint VCDirectoryBackspaceVisible = 1245;
/// <summary>
/// 1251
/// </summary>
public const uint VCSelfViewTogglePress = 1251;
/// <summary>
/// 1252
/// </summary>
public const uint VCLayoutTogglePress = 1252;
/// <summary>
/// 1253
/// </summary>
public const uint VCSelfViewPipTogglePress = 1253;
/// <summary>
/// 1254
/// </summary>
public const uint VCLayoutToggleEnable = 1254;
/// <summary>
/// 1255
/// </summary>
public const uint VCMinMaxPress = 1255;
/// <summary>
/// 1256
/// </summary>
public const uint VCMinMaxEnable = 1256;
/// <summary>
/// 1260
/// </summary>
public const uint VCCameraModeBarVisible = 1260;
/// <summary>
/// 1261
/// </summary>
public const uint VCCameraSelectBarWithoutModeVisible = 1261;
/// <summary>
/// 1262
/// </summary>
public const uint VCCameraAutoModeIsOnFb = 1262;
/// <summary>
/// 1271
/// </summary>
public const uint VCCameraZoomIn = 1271;
/// <summary>
/// 1272
/// </summary>
public const uint VCCameraZoomOut = 1272;
/// <summary>
/// 1280
/// </summary>
public const uint VCCameraPresetSavedLabelVisible = 1280;
/// <summary>
/// 1281
/// </summary>
public const uint VCCameraPreset1 = 1281;
/// <summary>
/// 1282
/// </summary>
public const uint VCCameraPreset2 = 1282;
/// <summary>
/// 1283
/// </summary>
public const uint VCCameraPreset3 = 1283;
/// <summary>
/// 1291
/// </summary>
public const uint VCCameraPreset1Visible = 1291;
/// <summary>
/// 1292
/// </summary>
public const uint VCCameraPreset2Visible = 1292;
/// <summary>
/// 1293
/// </summary>
public const uint VCCameraPreset3Visible = 1293;
// Letter joins start at 2921;
//******************************************************
// Environment Joins
// Popup Container
/// <summary>
/// 2001 - 2004
/// </summary>
public const uint EnvironmentBackgroundSubpageVisibleBase = 2000;
// ColumnOne
/// <summary>
/// 2011 - 2015
/// </summary>
public const uint EnvironmentColumnOneLightingTypeVisibleBase = 2010;
/// <summary>
/// 2016 - 2020
/// </summary>
public const uint EnvironmentColumnOneShadingTypeVisibleBase = 2015;
// ColumnTwo
/// <summary>
/// 2021 - 2025
/// </summary>
public const uint EnvironmentColumnTwoLightingTypeVisibleBase = 2020;
/// <summary>
/// 2026 - 2030
/// </summary>
public const uint EnvironmentColumnTwoShadingTypeVisibleBase = 2025;
// ColumnThree
/// <summary>
/// 2031 - 2035
/// </summary>
public const uint EnvironmentColumnThreeLightingTypeVisibleBase = 2030;
/// <summary>
/// 2036 - 2040
/// </summary>
public const uint EnvironmentColumnThreeShadingTypeVisibleBase = 2035;
// ColumnFour
/// <summary>
/// 2041 - 2045
/// </summary>
public const uint EnvironmentColumnFourLightingTypeVisibleBase = 2040;
/// <summary>
/// 2046 - 2050
/// </summary>
public const uint EnvironmentColumnFourShadingTypeVisibleBase = 2045;
// Button press
/// <summary>
/// 2051 - 2060
/// </summary>
public const uint EnvironmentColumnOneButtonPressBase = 2050;
/// <summary>
/// 2061 - 2070
/// </summary>
public const uint EnvironmentColumnTwoButtonPressBase = 2060;
/// <summary>
/// 2071 - 2080
/// </summary>
public const uint EnvironmentColumnThreeButtonPressBase = 2070;
/// <summary>
/// 2081 - 2090
/// </summary>
public const uint EnvironmentColumnFourButtonPressBase = 2080;
// Button visibility
/// <summary>
/// 2151 - 2160
/// </summary>
public const uint EnvironmentColumnOneButtonVisibleBase = 2150;
/// <summary>
/// 2161 - 2170
/// </summary>
public const uint EnvironmentColumnTwoButtonVisibleBase = 2160;
/// <summary>
/// 2171 - 2180
/// </summary>
public const uint EnvironmentColumnThreeButtonVisibleBase = 2170;
/// <summary>
/// 2181 - 2190
/// </summary>
public const uint EnvironmentColumnFourButtonVisibleBase = 2180;
//******************************************************
/// <summary>
/// 3101
/// </summary>
public const uint TechExitButton = 3101;
/// <summary>
/// 3106
/// </summary>
public const uint TechCommonItemsVisbible = 3106;
/// <summary>
/// 3107
/// </summary>
public const uint TechSystemStatusVisible = 3107;
/// <summary>
/// 3108
/// </summary>
public const uint TechDisplayControlsVisible = 3108;
/// <summary>
/// 3109
/// </summary>
public const uint TechPanelSetupVisible = 3109;
/// <summary>
/// 3110
/// </summary>
public const uint TechAdvancedVolumeVisible = 3110;
/// <summary>
/// 3111
/// </summary>
public const uint TechAboutVisible = 3111;
/// <summary>
/// 3112
/// </summary>
public const uint TechSchedulerVisible = 3112;
//*****************************************************
/// <summary>
/// 3811
/// </summary>
public const uint VolumeSingleMute1Visible = 3811;
/// <summary>
/// 3812
/// </summary>
public const uint VolumeSlider1Press = 3812;
/// <summary>
/// 3813
/// </summary>
public const uint Volume1ProgramMutePressAndFB = 3813;
/// <summary>
/// 3821
/// </summary>
public const uint Volume2Visible = 3821;
/// <summary>
/// 3822
/// </summary>
public const uint VolumeSlider2Press = 3822;
/// <summary>
/// 3823
/// </summary>
public const uint Volume2MutePressAndFB = 3823;
/// <summary>
/// 3831
/// </summary>
public const uint Volume3Visible = 3831;
/// <summary>
/// 3832
/// </summary>
public const uint VolumeSlider3Press = 3832;
/// <summary>
/// 3833
/// </summary>
public const uint Volume3MutePressAndFB = 3833;
/// <summary>
/// 3841
/// </summary>
public const uint Volume4Visible = 3841;
/// <summary>
/// 3842
/// </summary>
public const uint VolumeSlider4Press = 3842;
/// <summary>
/// 3843
/// </summary>
public const uint Volume4MutePressAndFB = 3843;
/// <summary>
/// 3851
/// </summary>
public const uint Volume5Visible = 3851;
/// <summary>
/// 3852
/// </summary>
public const uint VolumeSlider5Press = 3852;
/// <summary>
/// 3853
/// </summary>
public const uint Volume5MutePressAndFB = 3853;
/// <summary>
/// 3861
/// </summary>
public const uint Volume6Visible = 3861;
/// <summary>
/// 3862
/// </summary>
public const uint VolumeSlider6Press = 3862;
/// <summary>
/// 3863
/// </summary>
public const uint Volume6MutePressAndFB = 3863;
/// <summary>
/// 3869 - when the system is off and the gear is pressed
/// </summary>
public const uint VolumesPagePowerOffVisible = 3869;
/// <summary>
/// 3870
/// </summary>
public const uint VolumesPageVisible = 3870;
/// <summary>
/// 3871
/// </summary>
public const uint VolumeDualMute1Visible = 3871;
/// <summary>
/// 3874
/// </summary>
public const uint Volume1SpeechMutePressAndFB = 3874;
/// <summary>
/// 3875
/// </summary>
public const uint Volume1BackerVisibility = 3875;
/// <summary>
/// 3891
/// </summary>
public const uint VolumeDefaultPress = 3891;
/// <summary>
/// 3951
/// </summary
public const uint HeaderIcon1Press = 3951;
/// <summary>
/// 3952
/// </summary>
public const uint HeaderIcon2Press = 3952;
/// <summary>
/// 3953
/// </summary>
public const uint HeaderIcon3Press = 3953;
/// <summary>
/// 3954
/// </summary>
public const uint HeaderIcon4Press = 3954;
/// <summary>
/// 3955
/// </summary>
public const uint HeaderIcon5Press = 3955;
/// 3960
/// </summary>
public const uint HeaderPopupCaretsSubpageVisibile = 3960;
/// <summary>
/// 3961
/// </summary>
public const uint HeaderCaret1Visible = 3961;
/// <summary>
/// 3962
/// </summary>
public const uint HeaderCaret2Visible = 3962;
/// <summary>
/// 3963
/// </summary>
public const uint HeaderCaret3Visible = 3963;
/// <summary>
/// 3964
/// </summary>
public const uint HeaderCaret4Visible = 3964;
/// <summary>
/// 3965
/// </summary>
public const uint HeaderCaret5Visible = 3965;
/// <summary>
/// 3999
/// </summary>
public const uint GenericModalVisible = 3999;
/// <summary>
/// 12345
/// </summary>
public const uint AvNoControlsSubVisible = 12345;
// 10000 - 14999 are general "source" pages
/// <summary>
/// 15001
/// </summary>
public const uint StartPageVisible = 15001;
/// <summary>
/// 15002 Shows the start page in the source controls area of the screen
/// </summary>
public const uint TapToBeginVisible = 15002;
/// <summary>
/// 15003 Message text when no source is showing
/// </summary>
public const uint SelectASourceVisible = 15003;
/// <summary>
/// 15004
/// </summary>
public const uint RoomIsOn = 15004;
/// <summary>
/// 15005 Shows always-on volume control subpage with only audio mute
/// </summary>
public const uint VolumeControlsSingleMuteVisible = 15005;
/// <summary>
/// 15006 Shows always-on volume control subpage with mic and audio mutes
/// </summary>
public const uint VolumeControlsDualMuteVisible = 15006;
/// <summary>
/// 15010
/// </summary>
public const uint ShowPanelSetupPress = 15010;
/// <summary>
/// 15011 - Top bar with room name and button that pops up dialog with room data
/// </summary>
public const uint TopBarHabaneroVisible = 15011;
/// <summary>
/// 15012
/// </summary>
public const uint SourceStagingBarVisible = 15012;
/// <summary>
/// 15013
/// </summary>
public const uint PowerOffStep1Visible = 15013;
/// <summary>
/// 15014
/// </summary>
public const uint PowerOffStep2Visible = 15014;
/// <summary>
/// 15015
/// </summary>
public const uint ShowPowerOffPress = 15015;
/// <summary>
/// 15016
/// </summary>
public const uint PowerOffMorePress = 15016;
/// <summary>
/// 15017
/// </summary>
public const uint StagingPageAdditionalArrowsVisible = 15017;
/// <summary>
/// 15018 The Header with dynamic buttons
/// </summary>
public const uint TopBarHabaneroDynamicVisible = 15018;
/// <summary>
/// 15019 Shown when system is starting and not ready for use
/// </summary>
public const uint SystemInitializingVisible = 15019;
/// <summary>
/// 15020
/// </summary>
public const uint PanelSetupVisible = 15020;
/// <summary>
/// 15021
/// </summary>
public const uint SourceWaitOverlayVisible = 15021;
/// <summary>
/// 15022
/// </summary>
public const uint ActivityFooterVisible = 15022;
/// <summary>
/// 15024
/// </summary>
public const uint HeaderCallStatusLeftPositionVisible = 15024;
/// <summary>
/// 15025
/// </summary>
public const uint HeaderCallStatusRightPositionVisible = 15025;
/// <summary>
/// 15027
/// </summary>
public const uint HeaderCallStatusLabelPress = 15027;
/// <summary>
/// 15028 The gear button in header
/// </summary>
public const uint FIXFIX_HeaderGearButtonPress_FIXFIX = 15028;
/// <summary>
/// 15029 the room button in header
/// </summary>
public const uint HeaderRoomButtonPress = 15029;
/// <summary>
/// 15030 Visibility for room data popup
/// </summary>
public const uint RoomHeaderInfoPageVisible = 15030;
/// <summary>
/// 15031
/// </summary>
public const uint AllRoomsOffPress = 15031;
/// <summary>
/// 15032
/// </summary>
public const uint DisplayPowerTogglePress = 15032;
/// <summary>
/// 15033
/// </summary>
public const uint PowerOffCancelPress = 15033;
/// <summary>
/// 15034
/// </summary>
public const uint PowerOffConfirmPress = 15034;
/// <summary>
/// 15035
/// </summary>
public const uint VolumeButtonPopupPress = 15035;
/// <summary>
/// 15035
/// </summary>
public const uint VolumeButtonPopupVisible = 15035;
/// <summary>
/// 15036
/// </summary>
public const uint VolumeGaugePopupVisible = 15036;
/// <summary>
/// 15037
/// </summary>
public const uint GearButtonVisible = 15037;
/// <summary>
/// 15038
/// </summary>
public const uint CalendarHeaderButtonVisible = 15038;
/// <summary>
/// 15039
/// </summary>
public const uint CalendarHeaderButtonPress = 15039;
/// <summary>
/// 15040
/// </summary>
public const uint CallStatusPageVisible = 15040;
/// <summary>
/// 15041
/// </summary>
public const uint LightsPageVisible = 15041;
/// <summary>
/// 15042 Closes whichever interlocked modal is open
/// </summary>
public const uint InterlockedModalClosePress = 15042;
/// <summary>
/// 15043 Vis for modal backer for full-screen source
/// </summary>
public const uint SourceBackgroundOverlayVisible = 15043;
/// <summary>
/// 15044 Close button for source modal overlay
/// </summary>
public const uint SourceBackgroundOverlayClosePress = 15044;
/// <summary>
/// 15045
/// </summary>
public const uint ZoomRoomContentSharingVisible = 15045;
/// <summary>
/// 15046
/// </summary>
public const uint MeetingsOrContacMethodsListVisible = 15046;
/// <summary>
/// 15047 The "Join" button on the next meeting ribbon
/// </summary>
public const uint NextMeetingJoinPress = 15047;
/// <summary>
/// 15048 Dismisses the ribbon
/// </summary>
public const uint NextMeetingModalClosePress = 15048;
/// <summary>
/// 15049
/// </summary>
public const uint NextMeetingModalVisible = 15049;
/// <summary>
/// 15050
/// </summary>
public const uint NextMeetingNotificationRibbonVisible = 15050;
/// <summary>
/// 15051
/// </summary>
public const uint Display1SelectPressAndFb = 15051;
/// <summary>
/// 15052
/// </summary>
public const uint Display1ControlButtonEnable = 15052;
/// <summary>
/// 15053
/// </summary>
public const uint Display1ControlButtonPress = 15053;
/// <summary>
/// 15054
/// </summary>
public const uint Display1AudioButtonEnable = 15054;
/// <summary>
/// 15055
/// </summary>
public const uint Display1AudioButtonPressAndFb = 15055;
/// <summary>
/// 15056
/// </summary>
public const uint Display2SelectPressAndFb = 15056;
/// <summary>
/// 15057
/// </summary>
public const uint Display2ControlButtonEnable = 15057;
/// <summary>
/// 15058
/// </summary>
public const uint Display2ControlButtonPress = 15058;
/// <summary>
/// 15059
/// </summary>
public const uint Display2AudioButtonEnable = 15059;
/// <summary>
/// 15060
/// </summary>
public const uint Display2AudioButtonPressAndFb = 15060;
/// <summary>
/// 15061 Reveals the dual-display subpage
/// </summary>
public const uint DualDisplayPageVisible = 15061;
/// <summary>
/// 15062 Reveals the toggle switch for the sharing mode
/// </summary>
public const uint ToggleSharingModeVisible = 15062;
/// <summary>
/// 15063 Press for the toggle mode switch
/// </summary>
public const uint ToggleSharingModePress = 15063;
/// <summary>
/// 15064
/// </summary>
public const uint LogoDefaultVisible = 15064;
/// <summary>
/// 15065
/// </summary>
public const uint LogoUrlVisible = 15065;
/// <summary>
/// 15066 - Reveals the active calls header item
/// </summary>
public const uint HeaderActiveCallsListVisible = 15066;
/// <summary>
/// 15067
/// </summary>
public const uint NotificationRibbonVisible = 15067;
/// <summary>
/// 15068
/// </summary>
public const uint HeaderMeetingInfoVisible = 15068;
/// <summary>
/// 15083 - Press for Call help desk on AC/VC
/// </summary>
public const uint HelpPageShowCallButtonPress = 15083;
/// <summary>
/// 15084 - Show the "call help desk" button on help page
/// </summary>
public const uint HelpPageShowCallButtonVisible = 15084;
/// <summary>
/// 15085 Visibility join for help subpage
/// </summary>
public const uint HelpPageVisible = 15085;
/// <summary>
/// 15086 Press for help header button
/// </summary>
public const uint HelpPress = 15086;
/// <summary>
/// 15088
/// </summary>
public const uint DateOnlyVisible = 15088;
/// <summary>
/// 15089
/// </summary>
public const uint TimeOnlyVisible = 15089;
/// <summary>
/// 15090
/// </summary>
public const uint DateAndTimeVisible = 15090;
/// <summary>
/// 15091
/// </summary>
public const uint SetupFullDistrib = 15091;
/// <summary>
/// 15092
/// </summary>
public const uint StartMCPageVisible = 15092;
/// <summary>
/// 15093
/// </summary>
public const uint RoomHeaderInfoMCPageVisible = 15093;
/// <summary>
/// 15094
/// </summary>
public const uint MCScreenSaverVisible = 15094;
/// <summary>
/// 15095
/// </summary>
public const uint MCScreenSaverPosition1Visible = 15095;
/// <summary>
/// 15096
/// </summary>
public const uint MCScreenSaverPosition2Visible = 15096;
/// <summary>
/// 15097
/// </summary>
public const uint MCScreenSaverPosition3Visible = 15097;
/// <summary>
/// 15098
/// </summary>
public const uint MCScreenSaverPosition4Visible = 15098;
/// <summary>
/// 15099
/// </summary>
public const uint MCScreenSaverClosePress = 15099;
// PIN dialogs ************************************
/// <summary>
/// 15201
/// </summary>
public const uint PinDialog4DigitVisible = 15201;
/// <summary>
/// 15206
/// </summary>
public const uint PinDialogCancelPress = 15206;
/// <summary>
/// 15207
/// </summary>
public const uint PinDialogErrorVisible = 15207;
/// <summary>
/// 15211
/// </summary>
public const uint PinDialogDot1 = 15211;
/// <summary>
/// 15212
/// </summary>
public const uint PinDialogDot2 = 15212;
/// <summary>
/// 15213
/// </summary>
public const uint PinDialogDot3 = 15213;
/// <summary>
/// 15214
/// </summary>
public const uint PinDialogDot4 = 15214;
// Password Prompt Dialog **************************
/// <summary>
/// 15301
/// </summary>
public const uint PasswordPromptDialogVisible = 15301;
/// <summary>
/// 15302
/// </summary>
public const uint PasswordPromptTextPress = 15302;
/// <summary>
/// 15306
/// </summary>
public const uint PasswordPromptCancelPress = 15306;
/// <summary>
/// 15307
/// </summary>
public const uint PasswordPromptErrorVisible = 15307;
}
}

View File

@@ -1,88 +0,0 @@
namespace PepperDash.Essentials
{
public class UISmartObjectJoin
{
//******************************************************
// Conference
/// <summary>
/// 1001 - The list that reveals in header to show calls
/// </summary>
public const uint CodecActiveCallsHeaderList = 1001;
// Video Conference
/// <summary>
/// 1201
/// </summary>
public const uint VCDialKeypad = 1201;
/// <summary>
/// 1202
/// </summary>
public const uint VCDirectoryList = 1202;
/// <summary>
/// 1203
/// </summary>
public const uint VCRecentsList = 1203;
/// <summary>
/// 1204
/// </summary>
public const uint VCFavoritesList = 1204;
/// <summary>
/// 1205 Layout buttons dynamic list
/// </summary>
public const uint VCLayoutsList = 1205;
/// <summary>
/// 1206 VC Camera Mode horizontal list
/// </summary>
public const uint VCCameraMode = 1206;
/// <summary>
/// 1207 VC Camera Mode Dpad
/// </summary>
public const uint VCCameraDpad = 1207;
/// <summary>
/// 1208 VC Camera Select
/// </summary>
public const uint VCCameraSelect = 1208;
//******************************************************
// General
/// <summary>
/// 3200 The staging, source-select list
/// </summary>
public const uint SourceStagingSRL = 3200;
/// <summary>
/// 3901 The Tech page menu list
/// </summary>
public const uint TechMenuList = 3901;
/// <summary>
/// 3902 Tech page statuses
/// </summary>
public const uint TechStatusList = 3902;
/// <summary>
/// 3903
/// </summary>
public const uint TechPinDialogKeypad = 3903;
/// <summary>
/// 3904 - Display controls on the tech page
/// </summary>
public const uint TechDisplayControlsList = 3904;
/// <summary>
/// 15018
/// </summary>
public const uint HeaderButtonList = 15018;
/// <summary>
/// 15022 The main activity footer
/// </summary>
public const uint ActivityFooterSRL = 15022;
/// <summary>
/// 15023 - The header meetings SRL
/// </summary>
public const uint MeetingListSRL = 15023;
}
}

View File

@@ -1,348 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
namespace PepperDash.Essentials
{
/// <summary>
/// Common string join number constants
/// </summary>
public class UIStringJoin
{
//******************************************************
// Codec
/// <summary>
/// 1001
/// </summary>
public const uint CodecAddressEntryText = 1001;
/// <summary>
/// 1002
/// </summary>
public const uint CodecDirectorySearchEntryText = 1002;
/// <summary>
/// 1004
/// </summary>
public const uint CallSharedSourceNameText = 1004;
/// <summary>
/// 1005
/// </summary>
public const uint MeetingIdText = 1005;
/// <summary>
/// 1006
/// </summary>
public const uint MeetingHostText = 1006;
/// <summary>
/// 1007
/// </summary>
public const uint MeetingPasswordText = 1007;
/// <summary>
/// 1008
/// </summary>
public const uint MeetingLeaveText = 1008;
/// <summary>
/// 1009
/// </summary>
public const uint MeetingNameText = 1009;
///<summary>
/// 1240 - Used to determine text for meeting start button
///</summary>
public const uint MeetingStartButtonText = 1240;
/// <summary>
/// 1201 - 1230 range of joins for recents list
/// </summary>
public const uint VCRecentListTextStart = 1201;
// RANGE IN USE
public const uint VCRecentListTextEnd = 1230;
/// <summary>
/// 1231 - 1261 range of joins for recent list time
/// </summary>
public const uint VCRecentListTimeTextStart = 1231;
// RANGE IN USE
public const uint VCRecentListTimeTextEnd = 1260;
/// <summary>
/// 1281
/// </summary>
public const uint VCCameraPresetLabel1 = 1281;
/// <summary>
/// 1282
/// </summary>
public const uint VCCameraPresetLabel2 = 1282;
/// <summary>
/// 1283
/// </summary>
public const uint VCCameraPresetLabel3 = 1283;
/// <summary>
/// 1291 - the current layout mode
/// </summary>
public const uint VCLayoutModeText = 1291;
/// <summary>
/// 1301 - 1400
/// </summary>
public const uint VCDirectoryListTextStart = 1301;
// RANGE IN USE
public const uint VCDirectoryListTextEnd = 1556;
/// <summary>
/// 1611 - 1615
/// </summary>
public const uint VCFavoritesStart = 1611;
// RANGE IN USE
public const uint VCFavoritesTextEnd = 1615;
//******************************************************
// Keyboard
/// <summary>
/// 1901
/// </summary>
//public const uint KeypadText = 2901;
//******************************************************
// Environment Joins
/// <summary>
/// 2001 - 2010
/// </summary>
public const uint EnvironmentColumnOneLabelBase = 2000;
/// <summary>
/// 2011 - 2020
/// </summary>
public const uint EnvironmentColumnTwoLabelBase = 2010;
/// <summary>
/// 2021 - 2030
/// </summary>
public const uint EnvironmentColumnThreeLabelBase = 2020;
/// <summary>
/// 2031 - 2040
/// </summary>
public const uint EnvironmentColumnFourLabelBase = 2030;
// 2050, 2060, 2070 and 2080 reserved for column device name labels
//******************************************************
/// <summary>
/// 3101 - This is the start of the range 3101 - 3120
/// </summary>
public const uint TechMenuButtonTextStart = 3101;
//----- through 3120
/// <summary>
/// 3201
/// </summary>
public const uint PasswordPromptMessageText = 3201;
/// <summary>
/// 3202
/// </summary>
public const uint PasswordPromptPasswordText = 3202;
/// <summary>
/// 3812
/// </summary>
public const uint AdvancedVolumeSlider1Text = 3812;
/// <summary>
/// 3822
/// </summary>
public const uint AdvancedVolumeSlider2Text = 3822;
/// <summary>
/// 3832
/// </summary>
public const uint AdvancedVolumeSlider3Text = 3832;
/// <summary>
/// 3842
/// </summary>
public const uint AdvancedVolumeSlider4Text = 3842;
/// <summary>
/// 3852
/// </summary>
public const uint AdvancedVolumeSlider5Text = 3852;
/// <summary>
/// 3862
/// </summary>
public const uint AdvancedVolumeSlider6Text = 3862;
/// <summary>
/// 3901
/// </summary>
public const uint CurrentRoomName = 3901;
/// <summary>
/// 3902
/// </summary>
public const uint CurrentSourceName = 3902;
/// <summary>
/// 3903
/// </summary>
public const uint CurrentSourceIcon = 3903;
/// <summary>
/// 3904 - Phone number for room header
/// </summary>
public const uint RoomPhoneText = 3904;
/// <summary>
/// 3905 - Video address/number for room header
/// </summary>
public const uint RoomVideoAddressText = 3905;
/// <summary>
/// 3906 - The separator for verbose-header text on addresses
/// </summary>
public const uint RoomAddressPipeText = 3906;
/// <summary>
/// 3907 - The user code for mobile control
/// </summary>
public const uint RoomUserCode = 3907;
/// <summary>
/// 3908 - The url for the mobile control server
/// </summary>
public const uint RoomMcUrl = 3908;
/// <summary>
/// 3909 - The url for the mobile control QR Code image
/// </summary>
public const uint RoomMcQrCodeUrl = 3909;
/// <summary>
/// 3911
/// </summary>
public const uint PowerOffMessage = 3911;
/// <summary>
/// 3912
/// </summary>
public const uint StartPageMessage = 3912;
/// <summary>
/// 3913
/// </summary>
public const uint StartActivityText = 3913;
/// <summary>
/// 3914 Title bar label for source overlay
/// </summary>
public const uint SourceBackgroundOverlayTitle = 3914;
/// <summary>
/// 3915
/// </summary>
public const uint NotificationRibbonText = 3915;
/// <summary>
/// 3916 The "active call" label
/// </summary>
public const uint HeaderCallStatusLabel = 3916;
/// <summary>
/// 3919 Mesage on init page
/// </summary>
public const uint SystemInitializingMessage = 3919;
/// <summary>
/// 3922
/// </summary>
public const uint HelpMessage = 3922;
/// <summary>
/// 3923
/// </summary>
public const uint LogoUrlLightBkgnd = 3923;
/// <summary>
/// 3924 - the text on the "call help desk" button
/// </summary>
public const uint HelpPageCallButtonText = 3924;
/// <summary>
/// 3925
/// </summary>
public const uint LogoUrlDarkBkgnd = 3925;
/// <summary>
/// 3951
/// </summary>
public const uint HeaderButtonIcon1 = 3951;
/// <summary>
/// 3952
/// </summary>
public const uint HeaderButtonIcon2 = 3952;
/// <summary>
/// 3953
/// </summary>
public const uint HeaderButtonIcon3 = 3953;
/// <summary>
/// 3954
/// </summary>
public const uint HeaderButtonIcon4 = 3954;
/// <summary>
/// 3955
/// </summary>
public const uint HeaderButtonIcon5 = 3955;
/// <summary>
/// 3961 Name of source on display 1
/// </summary>
public const uint Display1SourceLabel = 3961;
/// <summary>
/// 3962 Title above display 1
/// </summary>
public const uint Display1TitleLabel = 3962;
/// <summary>
/// 3964 Name of source on display 2
/// </summary>
public const uint Display2SourceLabel = 3964;
/// <summary>
/// 3965 Title above display 2
/// </summary>
public const uint Display2TitleLabel = 3965;
/// <summary>
/// 3966
/// </summary>
public const uint NextMeetingStartTimeText = 3966;
/// <summary>
/// 3967
/// </summary>
public const uint NextMeetingEndTimeText = 3967;
/// <summary>
/// 3968
/// </summary>
public const uint NextMeetingTitleText = 3968;
/// <summary>
/// 3969
/// </summary>
public const uint NextMeetingNameText = 3969;
/// <summary>
/// 3970
/// </summary>
public const uint NextMeetingButtonLabel = 3970;
/// <summary>
/// 3971
/// </summary>
public const uint NextMeetingSecondaryButtonLabel = 3971;
/// <summary>
/// 3972
/// </summary>
public const uint NextMeetingFollowingMeetingText = 3972;
/// <summary>
/// 3976
/// </summary>
public const uint MeetingsOrContactMethodListIcon = 3976;
/// <summary>
/// 3977
/// </summary>
public const uint MeetingsOrContactMethodListTitleText = 3977;
// ------------------------------------
//
// MODAL JOINS 3991 - 3999
//
// ------------------------------------
}
}

View File

@@ -1,54 +0,0 @@
namespace PepperDash.Essentials
{
/// <summary>
///
/// </summary>
public class UIUshortJoin
{
// Video Codec
/// <summary>
/// 1234: values 0 = Connect, 1 = End, 2 = Start Meeting
/// </summary>
public const uint VCStagingConnectButtonMode = 1234;
/// <summary>
/// 3812
/// </summary>
public const uint VolumeSlider1Value = 3812;
/// <summary>
/// 3822
/// </summary>
public const uint VolumeSlider2Value = 3822;
/// <summary>
/// 3832
/// </summary>
public const uint VolumeSlider3Value = 3832;
/// <summary>
/// 3842
/// </summary>
public const uint VolumeSlider4Value = 3842;
/// <summary>
/// 3852
/// </summary>
public const uint VolumeSlider5Value = 3852;
/// <summary>
/// 3862
/// </summary>
public const uint VolumeSlider6Value = 3862;
/// <summary>
/// 3922: 0-4, center->left. 5-8, center -> right.
/// </summary>
public const uint PresentationStagingCaretMode = 3922;
/// <summary>
/// 3923: 0-4, center->left. 5-8, center -> right.
/// </summary>
public const uint CallStagingCaretMode = 3923;
/// <summary>
/// 15024 - Modes 0: On hook, 1: Phone, 2: Video
/// </summary>
public const uint CallHeaderButtonMode = 15024;
}
}

View File

@@ -1,58 +0,0 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Crestron.SimplSharp;
//using Crestron.SimplSharpPro;
//using Crestron.SimplSharpPro.DeviceSupport;
//using PepperDash.Essentials.Core;
//using PepperDash.Essentials.Core.SmartObjects;
//namespace PepperDash.Essentials
//{
// public class SmartObjectHeaderButtonList : SmartObjectHelperBase
// {
// public SmartObjectHeaderButtonList(SmartObject so)
// : base(so, true)
// {
// }
// }
// public class HeaderListButton
// {
// public BoolInputSig SelectedSig { get; private set; }
// public BoolInputSig VisibleSig { get; private set; }
// public BoolOutputSig OutputSig { get; private set; }
// StringInputSig IconSig;
// public HeaderListButton(SmartObjectHeaderButtonList list, uint index)
// {
// var so = list.SmartObject;
// OutputSig = so.BooleanOutput["Item " + index + " Pressed"];
// SelectedSig = so.BooleanInput["Item " + index + " Selected"];
// VisibleSig = so.BooleanInput["Item " + index + " Visible"];
// IconSig = so.StringInput["Set Item " + index + " Icon Serial"];
// }
// public void SetIcon(string i)
// {
// IconSig.StringValue = i;
// }
// public void ClearIcon()
// {
// IconSig.StringValue = "Blank";
// }
// public static string Calendar = "Calendar";
// public static string Camera = "Camera";
// public static string Gear = "Gear";
// public static string Lights = "Lights";
// public static string Help = "Help";
// public static string OnHook = "DND";
// public static string Phone = "Phone";
// }
//}

View File

@@ -1,39 +0,0 @@
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
{
/// <summary>
///
/// </summary>
/// <param name="index"></param>
/// <param name="owner"></param>
/// <param name="buttonMode">0=Share, 1=Phone Call, 2=Video Call, 3=End Meeting</param>
/// <param name="pressAction"></param>
public SubpageReferenceListActivityItem(uint index, SubpageReferenceList owner,
ushort buttonMode, Action<bool> pressAction)
: base(index, owner)
{
Owner.GetBoolFeedbackSig(Index, 1).UserObject = pressAction;
Owner.UShortInputSig(Index, 1).UShortValue = buttonMode;
}
/// <summary>
/// Called by SRL to release all referenced objects
/// </summary>
public override void Clear()
{
Owner.BoolInputSig(Index, 1).UserObject = null;
Owner.UShortInputSig(Index, 1).UShortValue = 0;
}
}
}

View File

@@ -1,39 +0,0 @@
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
{
/// <summary>
///
/// </summary>
/// <param name="index"></param>
/// <param name="owner"></param>
/// <param name="buttonMode">0=Share, 1=Phone Call, 2=Video Call, 3=End Meeting</param>
/// <param name="pressAction"></param>
public SubpageReferenceListButtonAndModeItem(uint index, SubpageReferenceList owner,
ushort buttonMode, Action<bool> pressAction)
: base(index, owner)
{
Owner.GetBoolFeedbackSig(Index, 1).UserObject = pressAction;
Owner.UShortInputSig(Index, 1).UShortValue = buttonMode;
}
/// <summary>
/// Called by SRL to release all referenced objects
/// </summary>
public override void Clear()
{
Owner.BoolInputSig(Index, 1).UserObject = null;
Owner.UShortInputSig(Index, 1).UShortValue = 0;
}
}
}

View File

@@ -1,71 +0,0 @@
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; }
private IHasCurrentSourceInfoChange _room;
public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner,
SourceListItem sourceItem, Action<bool> routeAction)
: base(index, owner)
{
SourceItem = sourceItem;
owner.GetBoolFeedbackSig(index, 1).UserObject = new Action<bool>(routeAction);
owner.StringInputSig(index, 1).StringValue = SourceItem.PreferredName;
}
public void RegisterForSourceChange(IHasCurrentSourceInfoChange room)
{
_room = room;
room.CurrentSourceChange -= room_CurrentSourceInfoChange;
room.CurrentSourceChange += room_CurrentSourceInfoChange;
}
void room_CurrentSourceInfoChange(SourceListItem info, ChangeType type)
{
if (type == ChangeType.WillChange && info == SourceItem)
ClearFeedback();
else if (type == ChangeType.DidChange && info == SourceItem)
SetFeedback();
}
/// <summary>
/// Called by SRL to release all referenced objects
/// </summary>
public override void Clear()
{
Owner.BoolInputSig(Index, 1).UserObject = null;
Owner.StringInputSig(Index, 1).StringValue = "";
if(_room != null)
_room.CurrentSourceChange -= room_CurrentSourceInfoChange;
}
/// <summary>
/// Sets the selected feedback on the button
/// </summary>
public void SetFeedback()
{
Owner.BoolInputSig(Index, 1).BoolValue = true;
}
/// <summary>
/// Clears the selected feedback on the button
/// </summary>
public void ClearFeedback()
{
Owner.BoolInputSig(Index, 1).BoolValue = false;
}
}
}

View File

@@ -1,231 +0,0 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Crestron.SimplSharp;
//using Crestron.SimplSharpPro;
//using Crestron.SimplSharpPro.DeviceSupport;
//using PepperDash.Core;
//using PepperDash.Essentials.Core;
//using PepperDash.Essentials.Core.SmartObjects;
//using PepperDash.Essentials.Core.PageManagers;
//namespace PepperDash.Essentials
//{
// public class DualDisplaySimpleOrAdvancedRouting : PanelDriverBase
// {
// EssentialsPresentationPanelAvFunctionsDriver Parent;
// /// <summary>
// /// Smart Object 3200
// /// </summary>
// SubpageReferenceList SourcesSrl;
// /// <summary>
// /// For tracking feedback on last selected
// /// </summary>
// BoolInputSig LastSelectedSourceSig;
// /// <summary>
// /// The source that has been selected and is awaiting assignment to a display
// /// </summary>
// SourceListItem PendingSource;
// bool IsSharingModeAdvanced;
// public DualDisplaySimpleOrAdvancedRouting(EssentialsPresentationPanelAvFunctionsDriver parent) : base(parent.TriList)
// {
// Parent = parent;
// SourcesSrl = new SubpageReferenceList(TriList, 3200, 3, 3, 3);
// TriList.SetSigFalseAction(UIBoolJoin.ToggleSharingModePress, ToggleSharingModePressed);
// TriList.SetSigFalseAction(UIBoolJoin.Display1AudioButtonPressAndFb, Display1AudioPress);
// TriList.SetSigFalseAction(UIBoolJoin.Display1ControlButtonPress, Display1ControlPress);
// TriList.SetSigTrueAction(UIBoolJoin.Display1SelectPressAndFb, Display1Press);
// TriList.SetSigFalseAction(UIBoolJoin.Display2AudioButtonPressAndFb, Display2AudioPress);
// TriList.SetSigFalseAction(UIBoolJoin.Display2ControlButtonPress, Display2ControlPress);
// TriList.SetSigTrueAction(UIBoolJoin.Display2SelectPressAndFb, Display2Press);
// }
// /// <summary>
// ///
// /// </summary>
// public override void Show()
// {
// TriList.BooleanInput[UIBoolJoin.ToggleSharingModeVisible].BoolValue = true;
// TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = true;
// if(IsSharingModeAdvanced)
// TriList.BooleanInput[UIBoolJoin.DualDisplayPageVisible].BoolValue = true;
// else
// TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = true;
// base.Show();
// }
// /// <summary>
// ///
// /// </summary>
// //public override void Hide()
// //{
// // TriList.BooleanInput[UIBoolJoin.ToggleSharingModeVisible].BoolValue = false;
// // TriList.BooleanInput[UIBoolJoin.StagingPageVisible].BoolValue = false;
// // if(IsSharingModeAdvanced)
// // TriList.BooleanInput[UIBoolJoin.DualDisplayPageVisible].BoolValue = false;
// // else
// // TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
// // base.Hide();
// //}
// public void SetCurrentRoomFromParent()
// {
// if (IsSharingModeAdvanced)
// return; // add stuff here
// else
// SetupSourceListForSimpleRouting();
// }
// /// <summary>
// ///
// /// </summary>
// void SetupSourceListForSimpleRouting()
// {
// // get the source list config and set up the source list
// var config = ConfigReader.ConfigObject.SourceLists;
// if (config.ContainsKey(Parent.CurrentRoom.SourceListKey))
// {
// var srcList = config[Parent.CurrentRoom.SourceListKey]
// .Values.ToList().OrderBy(s => s.Order);
// // Setup sources list
// uint i = 1; // counter for UI list
// foreach (var srcConfig in srcList)
// {
// if (!srcConfig.IncludeInSourceList) // Skip sources marked this way
// continue;
// var sourceKey = srcConfig.SourceKey;
// var actualSource = DeviceManager.GetDeviceForKey(sourceKey) as Device;
// if (actualSource == null)
// {
// Debug.Console(0, "Cannot assign missing source '{0}' to source UI list",
// srcConfig.SourceKey);
// continue;
// }
// var localSrcItem = srcConfig; // lambda scope below
// var localIndex = i;
// SourcesSrl.GetBoolFeedbackSig(i, 1).UserObject = new Action<bool>(b =>
// {
// if (IsSharingModeAdvanced)
// {
// if (LastSelectedSourceSig != null)
// LastSelectedSourceSig.BoolValue = false;
// SourceListButtonPress(localSrcItem);
// LastSelectedSourceSig = SourcesSrl.BoolInputSig(localIndex, 1);
// LastSelectedSourceSig.BoolValue = true;
// }
// else
// Parent.CurrentRoom.DoSourceToAllDestinationsRoute(localSrcItem);
// });
// SourcesSrl.StringInputSig(i, 1).StringValue = srcConfig.PreferredName;
// i++;
// //var item = new SubpageReferenceListSourceItem(i++, SourcesSrl, srcConfig,
// // b => { if (!b) UiSelectSource(localSrcConfig); });
// //SourcesSrl.AddItem(item); // add to the SRL
// //item.RegisterForSourceChange(Parent.CurrentRoom);
// }
// SourcesSrl.Count = (ushort)(i - 1);
// Parent.CurrentRoom.CurrentSingleSourceChange += CurrentRoom_CurrentSourceInfoChange;
// Parent.CurrentRoom.CurrentDisplay1SourceChange += CurrentRoom_CurrentDisplay1SourceChange;
// Parent.CurrentRoom.CurrentDisplay2SourceChange += CurrentRoom_CurrentDisplay2SourceChange;
// }
// }
// void SetupSourceListForAdvancedRouting()
// {
// }
// void CurrentRoom_CurrentSourceInfoChange(IEssentialsRoom room, SourceListItem info, ChangeType type)
// {
// }
// void CurrentRoom_CurrentDisplay1SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type)
// {
// TriList.StringInput[UIStringJoin.Display1SourceLabel].StringValue = PendingSource.PreferredName;
// }
// void CurrentRoom_CurrentDisplay2SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type)
// {
// TriList.StringInput[UIStringJoin.Display2SourceLabel].StringValue = PendingSource.PreferredName;
// }
// /// <summary>
// ///
// /// </summary>
// void ToggleSharingModePressed()
// {
// Hide();
// IsSharingModeAdvanced = !IsSharingModeAdvanced;
// TriList.BooleanInput[UIBoolJoin.ToggleSharingModePress].BoolValue = IsSharingModeAdvanced;
// Show();
// }
// public void SourceListButtonPress(SourceListItem item)
// {
// // start the timer
// // show FB on potential source
// TriList.BooleanInput[UIBoolJoin.Display1AudioButtonEnable].BoolValue = false;
// TriList.BooleanInput[UIBoolJoin.Display1ControlButtonEnable].BoolValue = false;
// TriList.BooleanInput[UIBoolJoin.Display2AudioButtonEnable].BoolValue = false;
// TriList.BooleanInput[UIBoolJoin.Display2ControlButtonEnable].BoolValue = false;
// PendingSource = item;
// }
// void EnableAppropriateDisplayButtons()
// {
// TriList.BooleanInput[UIBoolJoin.Display1AudioButtonEnable].BoolValue = true;
// TriList.BooleanInput[UIBoolJoin.Display1ControlButtonEnable].BoolValue = true;
// TriList.BooleanInput[UIBoolJoin.Display2AudioButtonEnable].BoolValue = true;
// TriList.BooleanInput[UIBoolJoin.Display2ControlButtonEnable].BoolValue = true;
// if (LastSelectedSourceSig != null)
// LastSelectedSourceSig.BoolValue = false;
// }
// public void Display1Press()
// {
// EnableAppropriateDisplayButtons();
// Parent.CurrentRoom.SourceToDisplay1(PendingSource);
// // Enable end meeting
// }
// public void Display1AudioPress()
// {
// }
// public void Display1ControlPress()
// {
// }
// public void Display2Press()
// {
// EnableAppropriateDisplayButtons();
// Parent.CurrentRoom.SourceToDisplay2(PendingSource);
// }
// public void Display2AudioPress()
// {
// }
// public void Display2ControlPress()
// {
// }
// }
//}

View File

@@ -1,256 +0,0 @@
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.Core.Config;
using PepperDash.Essentials.Core.Shades;
using PepperDash.Essentials.Core.Lighting;
namespace PepperDash.Essentials
{
public class EssentialsEnvironmentDriver : PanelDriverBase
{
/// <summary>
/// Do I need this here?
/// </summary>
CrestronTouchpanelPropertiesConfig Config;
/// <summary>
/// The list of devices this driver is responsible for controlling
/// </summary>
public List<IKeyed> Devices { get; private set; }
/// <summary>
/// The parent driver for this
/// </summary>
EssentialsPanelMainInterfaceDriver Parent;
/// <summary>
/// The list of sub drivers for the devices
/// </summary>
public List<PanelDriverBase> DeviceSubDrivers { get; private set; }
public uint BackgroundSubpageJoin { get; private set; }
public EssentialsEnvironmentDriver(EssentialsPanelMainInterfaceDriver parent, CrestronTouchpanelPropertiesConfig config)
: base(parent.TriList)
{
Config = config;
Parent = parent;
Devices = new List<IKeyed>();
DeviceSubDrivers = new List<PanelDriverBase>();
Parent.AvDriver.PopupInterlock.StatusChanged += new EventHandler<StatusChangedEventArgs>(PopupInterlock_CurrentJoinChanged);
// Calculate the join offests for each device page and assign join actions for each button
}
void PopupInterlock_CurrentJoinChanged(object sender, StatusChangedEventArgs e)
{
// Hide this driver and all sub drivers if popup interlock is not shown
if (!e.IsShown || e.NewJoin != BackgroundSubpageJoin)
{
foreach (var driver in DeviceSubDrivers)
{
driver.Hide();
}
base.Hide();
}
}
void IsShownFeedback_OutputChange(object sender, EventArgs e)
{
}
/// <summary>
/// Shows this driver and all sub drivers
/// </summary>
public override void Show()
{
Parent.AvDriver.PopupInterlock.ShowInterlocked(BackgroundSubpageJoin);
foreach (var driver in DeviceSubDrivers)
{
driver.Show();
}
base.Show();
}
/// <summary>
/// Hides this driver and all sub drivers
/// </summary>
public override void Hide()
{
Parent.AvDriver.PopupInterlock.HideAndClear();
foreach (var driver in DeviceSubDrivers)
{
driver.Hide();
}
base.Hide();
}
public override void Toggle()
{
if (IsVisible)
Hide();
else
Show();
}
/// <summary>
/// Reads the device keys from the config and gets the devices by key
/// </summary>
public void GetDevicesFromConfig(Room.Config.EssentialsEnvironmentPropertiesConfig EnvironmentPropertiesConfig)
{
if (EnvironmentPropertiesConfig != null)
{
Devices.Clear();
DeviceSubDrivers.Clear();
uint column = 1;
foreach (var dKey in EnvironmentPropertiesConfig.DeviceKeys)
{
var device = DeviceManager.GetDeviceForKey(dKey);
if (device != null)
{
// Build the driver
var devicePanelDriver = GetPanelDriverForDevice(device, column);
// Add new PanelDriverBase SubDriver
if (devicePanelDriver != null)
{
Devices.Add(device);
DeviceSubDrivers.Add(devicePanelDriver);
Debug.Console(1, "Adding '{0}' to Environment Devices", device.Key);
column++;
// Quit if device count is exceeded
if (column > 4)
break;
}
else
Debug.Console(1, "Unable to build environment driver for device: '{0}'", device.Key);
}
}
SetupEnvironmentUiJoins();
}
else
{
Debug.Console(1, "Unable to get devices from config. No EnvironmentPropertiesConfig object in room config");
}
}
/// <summary>
/// Returns the appropriate panel driver for the device
/// </summary>
/// <param name="device"></param>
/// <param name="column"></param>
/// <returns></returns>
PanelDriverBase GetPanelDriverForDevice(IKeyed device, uint column)
{
PanelDriverBase panelDriver = null;
uint buttonPressJoinBase = 0;
uint buttonVisibleJoinBase = 0;
uint stringJoinBase = 0;
uint shadeTypeVisibleBase = 0;
uint lightingTypeVisibleBase = 0;
switch (column)
{
case 1:
{
buttonPressJoinBase = UIBoolJoin.EnvironmentColumnOneButtonPressBase;
buttonVisibleJoinBase = UIBoolJoin.EnvironmentColumnOneButtonVisibleBase;
stringJoinBase = UIStringJoin.EnvironmentColumnOneLabelBase;
shadeTypeVisibleBase = UIBoolJoin.EnvironmentColumnOneShadingTypeVisibleBase;
lightingTypeVisibleBase = UIBoolJoin.EnvironmentColumnOneLightingTypeVisibleBase;
break;
}
case 2:
{
buttonPressJoinBase = UIBoolJoin.EnvironmentColumnTwoButtonPressBase;
buttonVisibleJoinBase = UIBoolJoin.EnvironmentColumnTwoButtonVisibleBase;
stringJoinBase = UIStringJoin.EnvironmentColumnTwoLabelBase;
shadeTypeVisibleBase = UIBoolJoin.EnvironmentColumnTwoShadingTypeVisibleBase;
lightingTypeVisibleBase = UIBoolJoin.EnvironmentColumnTwoLightingTypeVisibleBase;
break;
}
case 3:
{
buttonPressJoinBase = UIBoolJoin.EnvironmentColumnThreeButtonPressBase;
buttonVisibleJoinBase = UIBoolJoin.EnvironmentColumnThreeButtonVisibleBase;
stringJoinBase = UIStringJoin.EnvironmentColumnThreeLabelBase;
shadeTypeVisibleBase = UIBoolJoin.EnvironmentColumnThreeShadingTypeVisibleBase;
lightingTypeVisibleBase = UIBoolJoin.EnvironmentColumnThreeLightingTypeVisibleBase;
break;
}
case 4:
{
buttonPressJoinBase = UIBoolJoin.EnvironmentColumnFourButtonPressBase;
buttonVisibleJoinBase = UIBoolJoin.EnvironmentColumnFourButtonVisibleBase;
stringJoinBase = UIStringJoin.EnvironmentColumnFourLabelBase;
shadeTypeVisibleBase = UIBoolJoin.EnvironmentColumnFourShadingTypeVisibleBase;
lightingTypeVisibleBase = UIBoolJoin.EnvironmentColumnFourLightingTypeVisibleBase;
break;
}
default:
{
Debug.Console(1, "Environment Driver: Invalid column number specified");
break;
}
}
// Determine if device is a shade or lighting type and construct the appropriate driver
if (device is ShadeBase)
{
panelDriver = new EssentialsShadeDriver(this, device.Key, buttonPressJoinBase, stringJoinBase, shadeTypeVisibleBase);
}
else if (device is LightingBase)
{
panelDriver = new EssentialsLightingDriver(this, device.Key, buttonPressJoinBase, buttonVisibleJoinBase, stringJoinBase, lightingTypeVisibleBase);
}
// Return the driver
return panelDriver;
}
/// <summary>
/// Determines the join values for the generic environment subpages
/// </summary>
void SetupEnvironmentUiJoins()
{
// Calculate which background subpage join to use
BackgroundSubpageJoin = UIBoolJoin.EnvironmentBackgroundSubpageVisibleBase + (uint)DeviceSubDrivers.Count;
}
}
public interface IEnvironmentSubdriver
{
uint SubpageVisibleJoin { get; }
}
}

View File

@@ -1,210 +0,0 @@
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.Core.Config;
using PepperDash.Essentials.Core.Lighting;
namespace PepperDash.Essentials
{
/// <summary>
/// Supports a lighting device with up to 6 scenes
/// </summary>
public class EssentialsLightingDriver : PanelDriverBase, IEnvironmentSubdriver
{
EssentialsEnvironmentDriver Parent;
public LightingBase LightingDevice { get; private set; }
public uint SubpageVisibleJoin { get; private set; }
/// <summary>
/// The base join number that all button visibilty joins are offset from
/// </summary>
uint ButtonVisibleJoinBase;
/// <summary>
/// The base join number that all button presses are offset from
/// </summary>
uint ButtonPressJoinBase;
/// <summary>
/// The base join number that all string lables are offset from
/// </summary>
uint StringJoinBase;
eLightsDeviceType DeviceType;
const uint DeviceNameJoinOffset = 50;
public EssentialsLightingDriver(EssentialsEnvironmentDriver parent, string deviceKey, uint buttonPressJoinBase, uint buttonVisibleJoinBase, uint stringJoinBase, uint subpageVisibleBase)
: base(parent.TriList)
{
Parent = parent;
ButtonPressJoinBase = buttonPressJoinBase;
ButtonVisibleJoinBase = buttonVisibleJoinBase;
StringJoinBase = stringJoinBase;
LightingDevice = DeviceManager.GetDeviceForKey(deviceKey) as LightingBase;
//LightingDevice.LightingSceneChange += new EventHandler<LightingSceneChangeEventArgs>(LightingDevice_LightingSceneChange);
SetDeviceType();
SetSubpageVisibleJoin(subpageVisibleBase);
SetUpDeviceName();
SetUpButtonActions();
}
/// <summary>
/// Handles setting feedback for the currently selected scene button
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void LightingDevice_LightingSceneChange(object sender, LightingSceneChangeEventArgs e)
{
uint joinOffset = 1;
foreach (var scene in LightingDevice.LightingScenes)
{
if (scene == e.CurrentLightingScene)
TriList.SetBool(ButtonPressJoinBase + joinOffset, true);
else
TriList.SetBool(ButtonPressJoinBase + joinOffset, false);
}
}
public override void Show()
{
TriList.SetBool(SubpageVisibleJoin, true);
base.Show();
}
public override void Hide()
{
TriList.SetBool(SubpageVisibleJoin, false);
base.Hide();
}
void SetUpDeviceName()
{
Parent.TriList.SetString(StringJoinBase + DeviceNameJoinOffset, LightingDevice.Name);
}
void SetDeviceType()
{
if (LightingDevice is ILightingScenes)
DeviceType = eLightsDeviceType.Scenes;
}
void SetSubpageVisibleJoin(uint subpageVisibleBase)
{
SubpageVisibleJoin = subpageVisibleBase + (uint)DeviceType;
}
/// <summary>
/// Drase
/// </summary>
void SetUpButtonActions()
{
if (DeviceType == eLightsDeviceType.Scenes)
{
uint joinOffset = ComputeJoinOffset();
// Clear preceding buttons
for (uint i = 1; i < joinOffset; i++)
{
TriList.SetString(StringJoinBase + i, "");
TriList.SetSigFalseAction(ButtonPressJoinBase + i, () => { });
TriList.SetBool(ButtonVisibleJoinBase + i, false);
}
foreach (var scene in LightingDevice.LightingScenes)
{
TriList.SetString(StringJoinBase + joinOffset, scene.Name);
var tempScene = scene;
TriList.SetSigFalseAction(ButtonPressJoinBase + joinOffset, () => LightingDevice.SelectScene(tempScene));
scene.IsActiveFeedback.LinkInputSig(TriList.BooleanInput[ButtonPressJoinBase + joinOffset]);
TriList.SetBool(ButtonVisibleJoinBase + joinOffset, true);
joinOffset++;
}
// Clear following buttons
for (uint i = joinOffset; i <= 6; i++)
{
TriList.SetString(StringJoinBase + i, "");
TriList.SetSigFalseAction(ButtonPressJoinBase + i, () => { });
TriList.SetBool(ButtonVisibleJoinBase + i, false);
}
}
}
/// <summary>
/// Computes the desired join offset to try to achieve the most centered appearance when using a subpage with 6 scene buttons
/// </summary>
/// <returns></returns>
uint ComputeJoinOffset()
{
uint joinOffset = 0;
switch (LightingDevice.LightingScenes.Count)
{
case 1:
{
joinOffset = 2;
break;
}
case 2:
{
joinOffset = 3;
break;
}
case 3:
{
joinOffset = 2;
break;
}
case 4:
{
joinOffset = 2;
break;
}
case 5:
{
joinOffset = 2;
break;
}
case 6:
{
joinOffset = 1;
break;
}
default:
{
break;
}
}
return joinOffset;
}
}
enum eLightsDeviceType : uint
{
None = 0,
Scenes = 1,
}
}

View File

@@ -1,117 +0,0 @@
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.Core.Config;
using PepperDash.Essentials.Core.Shades;
using PepperDash.Essentials.Devices.Common.Environment.Somfy;
namespace PepperDash.Essentials
{
public class EssentialsShadeDriver : PanelDriverBase, IEnvironmentSubdriver
{
EssentialsEnvironmentDriver Parent;
public ShadeBase ShadeDevice { get; private set; }
public uint SubpageVisibleJoin { get; private set; }
/// <summary>
/// The base join number that all button presses are offset from
/// </summary>
uint ButtonPressJoinBase;
/// <summary>
/// The base join number that all string lables are offset from
/// </summary>
uint StringJoinBase;
eShadeDeviceType DeviceType;
const uint DeviceNameJoinOffset = 50;
public EssentialsShadeDriver(EssentialsEnvironmentDriver parent, string deviceKey, uint buttonPressJoinBase, uint stringJoinBase, uint subpageVisibleBase)
: base(parent.TriList)
{
Parent = parent;
ButtonPressJoinBase = buttonPressJoinBase;
StringJoinBase = stringJoinBase;
ShadeDevice = DeviceManager.GetDeviceForKey(deviceKey) as ShadeBase;
SetDeviceType();
SetSubpageVisibleJoin(subpageVisibleBase);
SetUpDeviceName();
SetUpButtonActions();
}
public override void Show()
{
TriList.SetBool(SubpageVisibleJoin, true);
base.Show();
}
public override void Hide()
{
TriList.SetBool(SubpageVisibleJoin, false);
base.Hide();
}
void SetUpDeviceName()
{
Parent.TriList.SetString(StringJoinBase + DeviceNameJoinOffset, ShadeDevice.Name);
}
void SetDeviceType()
{
if (ShadeDevice is IShadesOpenCloseStop)
DeviceType = eShadeDeviceType.OpenCloseStop;
else if (ShadeDevice is IShadesOpenClose)
DeviceType = eShadeDeviceType.OpenClose;
}
void SetSubpageVisibleJoin(uint subpageVisibleBase)
{
SubpageVisibleJoin = subpageVisibleBase + (uint)DeviceType;
}
void SetUpButtonActions()
{
if(DeviceType == eShadeDeviceType.OpenClose)
{
TriList.SetSigTrueAction(ButtonPressJoinBase + 1, ShadeDevice.Open);
TriList.SetSigFalseAction(ButtonPressJoinBase + 2, ShadeDevice.Close);
}
else if(DeviceType == eShadeDeviceType.OpenCloseStop)
{
TriList.SetSigFalseAction(ButtonPressJoinBase + 1, ShadeDevice.Open);
TriList.SetSigFalseAction(ButtonPressJoinBase + 2, (ShadeDevice as IShadesOpenCloseStop).Stop);
if (ShadeDevice is IShadesOpenCloseStop)
TriList.SetString(StringJoinBase + 2, "Stop");
TriList.SetSigFalseAction(ButtonPressJoinBase + 3, ShadeDevice.Close);
}
}
}
enum eShadeDeviceType : uint
{
None = 0,
OpenCloseStop = 1,
OpenClose = 2,
DiscreteLevel = 3
}
}

View File

@@ -1,399 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.UI;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials
{
/// <summary>
///
/// </summary>
public class EssentialsHeaderDriver : PanelDriverBase
{
uint EnvironmentCaretVisible;
uint CalendarCaretVisible;
uint CallCaretVisible;
JoinedSigInterlock CaretInterlock;
CrestronTouchpanelPropertiesConfig Config;
/// <summary>
/// The parent driver for this
/// </summary>
EssentialsPanelMainInterfaceDriver Parent;
/// <summary>
/// Indicates that the SetHeaderButtons method has completed successfully
/// </summary>
public bool HeaderButtonsAreSetUp { get; private set; }
StringInputSig HeaderCallButtonIconSig;
public EssentialsHeaderDriver(EssentialsPanelMainInterfaceDriver parent, CrestronTouchpanelPropertiesConfig config)
: base(parent.TriList)
{
Config = config;
Parent = parent;
CaretInterlock = new JoinedSigInterlock(TriList);
}
void SetUpGear(IAVDriver avDriver, IEssentialsRoom currentRoom)
{
// Gear
TriList.SetString(UIStringJoin.HeaderButtonIcon5, "Gear");
TriList.SetSigHeldAction(UIBoolJoin.HeaderIcon5Press, 2000,
avDriver.ShowTech,
null,
() =>
{
if (currentRoom.OnFeedback.BoolValue)
{
avDriver.PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.VolumesPageVisible);
CaretInterlock.ShowInterlocked(UIBoolJoin.HeaderCaret5Visible);
}
else
{
avDriver.PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.VolumesPagePowerOffVisible);
CaretInterlock.ShowInterlocked(UIBoolJoin.HeaderCaret5Visible);
}
});
TriList.SetSigFalseAction(UIBoolJoin.TechExitButton, () =>
avDriver.PopupInterlock.HideAndClear());
}
public void SetUpHelpButton(EssentialsRoomPropertiesConfig roomConf)
{
// Help roomConf and popup
if (roomConf.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, roomConf.HelpMessage);
TriList.SetBool(UIBoolJoin.HelpPageShowCallButtonVisible, false);
TriList.SetString(UIStringJoin.HelpPageCallButtonText, null);
TriList.ClearBoolSigAction(UIBoolJoin.HelpPageShowCallButtonPress);
}
TriList.SetString(UIStringJoin.HeaderButtonIcon4, "Help");
TriList.SetSigFalseAction(UIBoolJoin.HeaderIcon4Press, () =>
{
string message = null;
var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey)
as IEssentialsHuddleSpaceRoom;
if (room != null)
message = room.PropertiesConfig.HelpMessage;
else
message = "Sorry, no help message available. No room connected.";
//TriList.StringInput[UIStringJoin.HelpMessage].StringValue = message;
Parent.AvDriver.PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HelpPageVisible);
CaretInterlock.ShowInterlocked(UIBoolJoin.HeaderCaret4Visible);
});
}
uint SetUpEnvironmentButton(EssentialsEnvironmentDriver environmentDriver, uint nextJoin)
{
if (environmentDriver != null)
{
var tempJoin = nextJoin;
TriList.SetString(tempJoin, "Lights");
EnvironmentCaretVisible = tempJoin + 10;
TriList.SetSigFalseAction(tempJoin, () =>
{
environmentDriver.Toggle();
CaretInterlock.ShowInterlocked(EnvironmentCaretVisible);
});
nextJoin--;
return nextJoin;
}
else
return nextJoin;
}
uint SetUpCalendarButton(EssentialsHuddleVtc1PanelAvFunctionsDriver avDriver, uint nextJoin)
{
// Calendar button
if (avDriver.CurrentRoom.ScheduleSource != null)
{
var tempJoin = nextJoin;
TriList.SetString(tempJoin, "Calendar");
CalendarCaretVisible = tempJoin + 10;
TriList.SetSigFalseAction(tempJoin, () =>
{
avDriver.CalendarPress();
CaretInterlock.ShowInterlocked(CalendarCaretVisible);
});
nextJoin--;
return nextJoin;
}
else
return nextJoin;
}
uint SetUpCallButton(EssentialsHuddleVtc1PanelAvFunctionsDriver avDriver, uint nextJoin)
{
// Call button
var tempJoin = nextJoin;
TriList.SetString(tempJoin, "DND");
CallCaretVisible = tempJoin + 10;
TriList.SetSigFalseAction(tempJoin, () =>
{
avDriver.ShowActiveCallsListOrMeetingInfo();
if(avDriver.CurrentRoom.InCallFeedback.BoolValue)
CaretInterlock.ShowInterlocked(CallCaretVisible);
});
HeaderCallButtonIconSig = TriList.StringInput[tempJoin];
nextJoin--;
return nextJoin;
}
/// <summary>
/// Evaluates the call status and sets the icon mode and text label
/// </summary>
public void ComputeHeaderCallStatus(VideoCodecBase codec)
{
if (codec == null)
{
Debug.Console(1, "ComputeHeaderCallStatus() cannot execute. codec is null");
return;
}
if (HeaderCallButtonIconSig == null)
{
Debug.Console(1, "ComputeHeaderCallStatus() cannot execute. HeaderCallButtonIconSig is null");
return;
}
var meetingInfoCodec = codec as IHasMeetingInfo;
// Set mode of header button
SetHeaderCallIcon(codec);
// Set the call status text
Debug.Console(1, "Active Call Count: {0}", codec.ActiveCalls.Count);
if (codec.ActiveCalls.Count > 0)
{
if (codec.ActiveCalls.Count == 1 && meetingInfoCodec == null)
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "1 Active Call");
else if (codec.ActiveCalls.Count == 1 && meetingInfoCodec != null)
{
var headerCallStatusLabel = meetingInfoCodec.MeetingInfo.IsSharingMeeting
? "Sharing-Only Meeting"
: "Active Meeting";
headerCallStatusLabel = meetingInfoCodec.MeetingInfo.WaitingForHost
? "Waiting For Host"
: headerCallStatusLabel;
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, headerCallStatusLabel);
}
else if (codec.ActiveCalls.Count > 1)
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, string.Format("{0} Active Calls", codec.ActiveCalls.Count));
}
else
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "No Active Calls");
}
private void SetHeaderCallIcon(VideoCodecBase codec)
{
if (!codec.IsInCall)
{
HeaderCallButtonIconSig.StringValue = "DND";
//HeaderCallButton.SetIcon(HeaderListButton.OnHook);
}
else if (codec.ActiveCalls.Any(c => c.Type == eCodecCallType.Video))
{
HeaderCallButtonIconSig.StringValue = "Misc-06_Dark";
}
//HeaderCallButton.SetIcon(HeaderListButton.Camera);
//TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 2);
else
{
HeaderCallButtonIconSig.StringValue = "Misc-09_Dark";
}
//HeaderCallButton.SetIcon(HeaderListButton.Phone);
//TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 1);
}
/// <summary>
/// Sets up Header Buttons for the EssentialsHuddleVtc1Room type
/// </summary>
public void SetupHeaderButtons(EssentialsHuddleVtc1PanelAvFunctionsDriver avDriver, IEssentialsHuddleVtc1Room currentRoom)
{
HeaderButtonsAreSetUp = false;
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
var roomConf = currentRoom.PropertiesConfig;
// Register for the PopupInterlock IsShowsFeedback event to tie the header carets subpage visiblity to it
Parent.AvDriver.PopupInterlock.StatusChanged -= PopupInterlock_StatusChanged;
Parent.AvDriver.PopupInterlock.StatusChanged += PopupInterlock_StatusChanged;
SetUpGear(avDriver, currentRoom);
SetUpHelpButton(roomConf);
uint nextJoin = 3953;
nextJoin = SetUpEnvironmentButton(Parent.EnvironmentDriver, nextJoin);
nextJoin = SetUpCalendarButton(avDriver, nextJoin);
nextJoin = SetUpCallButton(avDriver, nextJoin);
// blank any that remain
for (var i = nextJoin; i > 3950; i--)
{
TriList.SetString(i, "Blank");
TriList.SetSigFalseAction(i, () => { });
}
TriList.SetSigFalseAction(UIBoolJoin.HeaderCallStatusLabelPress,
() =>
{
avDriver.ShowActiveCallsListOrMeetingInfo();
if (avDriver.CurrentRoom.InCallFeedback.BoolValue)
CaretInterlock.ShowInterlocked(CallCaretVisible);
});
// Set Call Status Subpage Position
if (nextJoin == 3951)
{
// Set to right position
TriList.SetBool(UIBoolJoin.HeaderCallStatusLeftPositionVisible, false);
TriList.SetBool(UIBoolJoin.HeaderCallStatusRightPositionVisible, true);
}
else if (nextJoin == 3950)
{
// Set to left position
TriList.SetBool(UIBoolJoin.HeaderCallStatusLeftPositionVisible, true);
TriList.SetBool(UIBoolJoin.HeaderCallStatusRightPositionVisible, false);
}
HeaderButtonsAreSetUp = true;
ComputeHeaderCallStatus(currentRoom.VideoCodec);
}
/// <summary>
/// Sets up Header Buttons for the EssentialsHuddleSpaceRoom type
/// </summary>
public void SetupHeaderButtons(EssentialsHuddlePanelAvFunctionsDriver avDriver, IEssentialsHuddleSpaceRoom currentRoom)
{
HeaderButtonsAreSetUp = false;
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
var roomConf = currentRoom.PropertiesConfig;
// Register for the PopupInterlock IsShowsFeedback event to tie the header carets subpage visiblity to it
Parent.AvDriver.PopupInterlock.StatusChanged -= PopupInterlock_StatusChanged;
Parent.AvDriver.PopupInterlock.StatusChanged += PopupInterlock_StatusChanged;
SetUpGear(avDriver, currentRoom);
SetUpHelpButton(roomConf);
uint nextJoin = 3953;
nextJoin = SetUpEnvironmentButton(Parent.EnvironmentDriver, nextJoin);
// blank any that remain
for (var i = nextJoin; i > 3950; i--)
{
TriList.SetString(i, "Blank");
TriList.SetSigFalseAction(i, () => { });
}
HeaderButtonsAreSetUp = true;
}
///// <summary>
///// Whenever a popup is shown/hidden, show/hide the header carets subpage and set the visibility of the correct caret
///// </summary>
///// <param name="sender"></param>
///// <param name="e"></param>
//void IsShownFeedback_OutputChange(object sender, EventArgs e)
//{
// var popupInterlockIsShown = Parent.AvDriver.PopupInterlock.IsShown;
// // Set the visible state for the HeaderPopupCaretsSubpage to match that of the PopupInterlock state
// TriList.SetBool(UIBoolJoin.HeaderPopupCaretsSubpageVisibile, popupInterlockIsShown);
// // Clear all caret visibility
// for (uint i = UIBoolJoin.HeaderCaret5Visible; i >= UIBoolJoin.HeaderCaret1Visible; i--)
// {
// TriList.SetBool(i, false);
// }
// // Set the current caret visible if the popup is still shown
// if (popupInterlockIsShown)
// TriList.SetBool(NextCaretVisible, true);
//}
/// <summary>
/// Whenever a popup is shown/hidden, show/hide the header carets subpage and set the visibility of the correct caret
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void PopupInterlock_StatusChanged(object sender, StatusChangedEventArgs e)
{
// Set the visible state for the HeaderPopupCaretsSubpage to match that of the PopupInterlock state
bool headerPopupShown = false;
// Check if the popup interlock is shown, and if one of the header popups is current, then show the carets subpage
if (e.IsShown)
{
if (Parent.EnvironmentDriver != null && e.NewJoin == Parent.EnvironmentDriver.BackgroundSubpageJoin)
headerPopupShown = true;
else if (e.NewJoin == UIBoolJoin.HeaderActiveCallsListVisible)
headerPopupShown = true;
else if (e.NewJoin == UIBoolJoin.HeaderMeetingInfoVisible)
headerPopupShown = true;
else if (e.NewJoin == UIBoolJoin.HelpPageVisible)
headerPopupShown = true;
else if (e.NewJoin == UIBoolJoin.MeetingsOrContacMethodsListVisible)
headerPopupShown = true;
else if (e.NewJoin == UIBoolJoin.VolumesPagePowerOffVisible || e.NewJoin == UIBoolJoin.VolumesPageVisible)
headerPopupShown = true;
}
// Set the carets subpage visibility
TriList.SetBool(UIBoolJoin.HeaderPopupCaretsSubpageVisibile, headerPopupShown);
if (!e.IsShown)
CaretInterlock.HideAndClear();
}
}
}

View File

@@ -1,168 +0,0 @@
using System;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.SmartObjects;
namespace PepperDash.Essentials
{
/// <summary>
///
/// </summary>
public class EssentialsPanelMainInterfaceDriver : PanelDriverBase, IHasScreenSaverController, IDisposable
{
CTimer InactivityTimer;
/// <summary>
/// Assign the appropriate A/V driver.
/// Want to keep the AvDriver alive, because it may hold states
/// </summary>
public IAVDriver AvDriver { get; set;}
public EssentialsHeaderDriver HeaderDriver { get; set; }
public EssentialsEnvironmentDriver EnvironmentDriver { get; set; }
public PanelDriverBase CurrentChildDriver { get; private set; }
public ScreenSaverController ScreenSaverController { get; set; }
private readonly long _timeoutMs;
CrestronTouchpanelPropertiesConfig Config;
/// <summary>
/// The main interlock for popups
/// </summary>
//public JoinedSigInterlock PopupInterlock { get; private set; }
public EssentialsPanelMainInterfaceDriver(BasicTriListWithSmartObject trilist,
CrestronTouchpanelPropertiesConfig config)
: base(trilist)
{
Config = config;
_timeoutMs = Config.ScreenSaverTimeoutMin * 60 * 1000;
var tsx52or60 = trilist as Tswx52ButtonVoiceControl;
if (tsx52or60 != null)
{
tsx52or60.ExtenderTouchDetectionReservedSigs.Use();
tsx52or60.ExtenderTouchDetectionReservedSigs.DeviceExtenderSigChange += ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange;
tsx52or60.ExtenderTouchDetectionReservedSigs.Time.UShortValue = 1;
ManageInactivityTimer();
}
else
{
var tswx70 = trilist as TswX70Base;
if (tswx70 != null)
{
tswx70.ExtenderTouchDetectionReservedSigs.Use();
tswx70.ExtenderTouchDetectionReservedSigs.DeviceExtenderSigChange += ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange;
tswx70.ExtenderTouchDetectionReservedSigs.Time.UShortValue = 1;
ManageInactivityTimer();
}
}
}
#region IDisposable Members
public void Dispose()
{
var avDriver = AvDriver as PanelDriverBase;
if (avDriver != null)
{
avDriver.Hide();
}
if (ScreenSaverController != null)
{
ScreenSaverController.Dispose();
}
if (HeaderDriver != null)
{
HeaderDriver.Hide();
}
if (EnvironmentDriver != null)
{
EnvironmentDriver.Hide();
}
if (CurrentChildDriver != null)
{
CurrentChildDriver.Hide();
}
}
#endregion
void ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange(Crestron.SimplSharpPro.DeviceExtender currentDeviceExtender, Crestron.SimplSharpPro.SigEventArgs args)
{
if (args.Sig.BoolValue)
{
ManageInactivityTimer();
}
}
private void ManageInactivityTimer()
{
if (InactivityTimer != null)
{
InactivityTimer.Reset(_timeoutMs);
}
else
{
InactivityTimer = new CTimer((o) => InactivityTimerExpired(), _timeoutMs);
}
}
void InactivityTimerExpired()
{
InactivityTimer.Stop();
InactivityTimer.Dispose();
InactivityTimer = null;
ScreenSaverController.Show();
}
public override void Show()
{
CurrentChildDriver = null;
ShowSubDriver(AvDriver as PanelDriverBase);
base.Show();
}
public override void Hide()
{
TriList.BooleanInput[AvDriver.StartPageVisibleJoin].BoolValue = false;
base.Hide();
}
void ShowSubDriver(PanelDriverBase driver)
{
CurrentChildDriver = driver;
if (driver == null)
return;
this.Hide();
driver.Show();
}
/// <summary>
///
/// </summary>
public override void BackButtonPressed()
{
if(CurrentChildDriver != null)
CurrentChildDriver.BackButtonPressed();
}
}
public interface IHasScreenSaverController
{
ScreenSaverController ScreenSaverController { get; }
}
}

View File

@@ -1,326 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
using PepperDash.Essentials.Devices.Displays;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.UIDrivers
{
public class EssentialsHuddleTechPageDriver : PanelDriverBase
{
/// <summary>
///
/// </summary>
SmartObjectDynamicList MenuList;
/// <summary>
///
/// </summary>
SubpageReferenceList StatusList;
/// <summary>
/// The list of display controls
/// </summary>
SubpageReferenceList DisplayList;
/// <summary>
/// References lines in the list against device instances
/// </summary>
Dictionary<ICommunicationMonitor, uint> StatusListDeviceIndexes;
/// <summary>
///
/// </summary>
JoinedSigInterlock PagesInterlock;
/// <summary>
/// 1
/// </summary>
public const uint JoinText = 1;
CTimer PinAuthorizedTimer;
EssentialsRoomTechConfig Config;
StringBuilder PinEntryBuilder = new StringBuilder(4);
bool IsAuthorized;
SmartObjectNumeric PinKeypad;
/// <summary>
///
/// </summary>
/// <param name="trilist"></param>
/// <param name="parent"></param>
public EssentialsHuddleTechPageDriver(BasicTriListWithSmartObject trilist, EssentialsRoomTechConfig config)
: base(trilist)
{
Config = config;
PagesInterlock = new JoinedSigInterlock(trilist);
PagesInterlock.SetButDontShow(UIBoolJoin.TechSystemStatusVisible);
trilist.SetSigFalseAction(UIBoolJoin.TechExitButton, Hide);
MenuList = new SmartObjectDynamicList(trilist.SmartObjects[UISmartObjectJoin.TechMenuList],
true, 3100);
MenuList.SetFeedback(1, true); // initial fb
ushort count = 0;
MenuList.SetItemMainText(1, "System Status");
MenuList.SetItemButtonAction(1, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechSystemStatusVisible);
MenuList.SetFeedback(1, true);
});
MenuList.SetItemMainText(2, "Display Controls");
MenuList.SetItemButtonAction(2, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechDisplayControlsVisible);
MenuList.SetFeedback(2, true);
});
count = 2;
// Don't show panel setup on iPad or xpanel
if (TriList is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button)
{
count++;
MenuList.SetItemMainText(count, "Panel Setup");
MenuList.SetItemButtonAction(count, b =>
{
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechPanelSetupVisible);
MenuList.SetFeedback(count, true);
});
}
MenuList.Count = count;
BuildStatusList();
BuildDisplayList();
SetupPinModal();
}
/// <summary>
///
/// </summary>
public override void Show()
{
// divert to PIN if we need auth
if (IsAuthorized)
{
// Cancel the auth timer so we don't deauth after coming back in
if (PinAuthorizedTimer != null)
PinAuthorizedTimer.Stop();
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, true);
PagesInterlock.Show();
base.Show();
}
else
{
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, true);
}
}
/// <summary>
///
/// </summary>
public override void Hide()
{
// Leave it authorized for 60 seconds.
if (IsAuthorized)
PinAuthorizedTimer = new CTimer(o => {
IsAuthorized = false;
PinAuthorizedTimer = null;
}, 60000);
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, false);
PagesInterlock.Hide();
base.Hide();
}
/// <summary>
/// Wire up the keypad and buttons
/// </summary>
void SetupPinModal()
{
TriList.SetSigFalseAction(UIBoolJoin.PinDialogCancelPress, CancelPinDialog);
PinKeypad = new SmartObjectNumeric(TriList.SmartObjects[UISmartObjectJoin.TechPinDialogKeypad], true);
PinKeypad.Digit0.UserObject = new Action<bool>(b => { if (b)DialPinDigit('0'); });
PinKeypad.Digit1.UserObject = new Action<bool>(b => { if (b)DialPinDigit('1'); });
PinKeypad.Digit2.UserObject = new Action<bool>(b => { if (b)DialPinDigit('2'); });
PinKeypad.Digit3.UserObject = new Action<bool>(b => { if (b)DialPinDigit('3'); });
PinKeypad.Digit4.UserObject = new Action<bool>(b => { if (b)DialPinDigit('4'); });
PinKeypad.Digit5.UserObject = new Action<bool>(b => { if (b)DialPinDigit('5'); });
PinKeypad.Digit6.UserObject = new Action<bool>(b => { if (b)DialPinDigit('6'); });
PinKeypad.Digit7.UserObject = new Action<bool>(b => { if (b)DialPinDigit('7'); });
PinKeypad.Digit8.UserObject = new Action<bool>(b => { if (b)DialPinDigit('8'); });
PinKeypad.Digit9.UserObject = new Action<bool>(b => { if (b)DialPinDigit('9'); });
}
/// <summary>
///
/// </summary>
/// <param name="d"></param>
void DialPinDigit(char d)
{
PinEntryBuilder.Append(d);
var len = PinEntryBuilder.Length;
SetPinDotsFeedback(len);
// check it!
if (len == 4)
{
if (Config.Password == PinEntryBuilder.ToString())
{
IsAuthorized = true;
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
Show();
}
else
{
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, true);
new CTimer(o =>
{
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, false);
}, 1500);
}
PinEntryBuilder.Remove(0, len); // clear it either way
}
}
/// <summary>
/// Draws the dots as pin is entered
/// </summary>
/// <param name="len"></param>
void SetPinDotsFeedback(int len)
{
TriList.SetBool(UIBoolJoin.PinDialogDot1, len >= 1);
TriList.SetBool(UIBoolJoin.PinDialogDot2, len >= 2);
TriList.SetBool(UIBoolJoin.PinDialogDot3, len >= 3);
TriList.SetBool(UIBoolJoin.PinDialogDot4, len == 4);
}
/// <summary>
/// Does what it says
/// </summary>
void CancelPinDialog()
{
PinEntryBuilder.Remove(0, PinEntryBuilder.Length);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
}
/// <summary>
///
/// </summary>
void BuildStatusList()
{
StatusList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechStatusList, 3, 3, 3);
StatusListDeviceIndexes = new Dictionary<ICommunicationMonitor, uint>();
uint i = 0;
foreach (var d in DeviceManager.AllDevices)
{
// make sure it is both ICommunicationMonitor and a Device
var sd = d as ICommunicationMonitor;
if (sd == null)
continue;
var dd = sd as Device;
if(dd == null)
continue;
i++;
StatusList.StringInputSig(i, 1).StringValue = dd.Name;
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)sd.CommunicationMonitor.Status;
StatusListDeviceIndexes.Add(sd, i);
sd.CommunicationMonitor.StatusChange += CommunicationMonitor_StatusChange ;
}
StatusList.Count = (ushort)i;
}
/// <summary>
/// Builds the list of display controls
/// </summary>
void BuildDisplayList()
{
DisplayList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechDisplayControlsList, 10, 3, 3);
var devKeys = ConfigReader.ConfigObject.Devices.Where(d =>
d.Group.Equals("display", StringComparison.OrdinalIgnoreCase)
|| d.Group.Equals("projector", StringComparison.OrdinalIgnoreCase))
.Select(dd => dd.Key);
var disps = DeviceManager.AllDevices.Where(d =>
devKeys.Contains(d.Key));
ushort i = 0;
foreach (var disp in disps)
{
var display = disp as DisplayBase;
if (display != null)
{
i++;
DisplayList.StringInputSig(i, 1).StringValue = display.Name;
DisplayList.GetBoolFeedbackSig(i, 1).SetSigFalseAction(display.PowerOn);
DisplayList.GetBoolFeedbackSig(i, 2).SetSigFalseAction(display.PowerOff);
if (display is TwoWayDisplayBase)
{
var powerOnSig = DisplayList.BoolInputSig(i, 1);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkInputSig(powerOnSig);
var powerOffSig = DisplayList.BoolInputSig(1, 2);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkComplementInputSig(powerOffSig);
}
DisplayList.GetBoolFeedbackSig(i, 3).SetSigFalseAction(() =>
{ if (display is IInputHdmi1) (display as IInputHdmi1).InputHdmi1(); });
DisplayList.GetBoolFeedbackSig(i, 4).SetSigFalseAction(() =>
{ if (display is IInputHdmi2) (display as IInputHdmi2).InputHdmi2(); });
DisplayList.GetBoolFeedbackSig(i, 5).SetSigFalseAction(() =>
{ if (display is IInputHdmi3) (display as IInputHdmi3).InputHdmi3(); });
//DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
//{ if (display is IInputHdmi4) (display as IInputHdmi4).InputHdmi4(); });
DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
{ if (display is IInputDisplayPort1) (display as IInputDisplayPort1).InputDisplayPort1(); });
// Figure out some way to provide current input feedback
if (display is TwoWayDisplayBase)
{
(display as TwoWayDisplayBase).CurrentInputFeedback.OutputChange += CurrentInputFeedback_OutputChange;
}
}
}
DisplayList.Count = i;
}
void CurrentInputFeedback_OutputChange(object sender, EventArgs e)
{
}
/// <summary>
///
/// </summary>
void CommunicationMonitor_StatusChange(object sender, MonitorStatusChangeEventArgs e)
{
var c = sender as ICommunicationMonitor;
if (c != null && StatusListDeviceIndexes.ContainsKey(c))
{
var i = StatusListDeviceIndexes[c];
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)e.Status;
}
}
}
}

View File

@@ -1,49 +0,0 @@
//using System;
//using System.Linq;
//using System.Collections.Generic;
//using Crestron.SimplSharp;
//using Crestron.SimplSharpPro;
//using Crestron.SimplSharpPro.DeviceSupport;
//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 EssentialsHuddleVtc1PresentationUiDriver : PanelDriverBase
// {
// /// <summary>
// ///
// /// </summary>
// EssentialsHuddleVtc1Room CurrentRoom;
// public EssentialsHuddleVtc1PresentationUiDriver(BasicTriListWithSmartObject triList,
// EssentialsHuddleVtc1Room room)
// : base(triList)
// {
// CurrentRoom = room;
// }
// /// <summary>
// /// Smart Object 3200
// /// </summary>
// SubpageReferenceList SourceStagingSrl;
// /// <summary>
// /// The AV page mangagers that have been used, to keep them alive for later
// /// </summary>
// Dictionary<object, PageManager> PageManagers = new Dictionary<object, PageManager>();
// /// <summary>
// /// Current page manager running for a source
// /// </summary>
// PageManager CurrentSourcePageManager;
// }
//}

View File

@@ -1,175 +0,0 @@
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.Core;
namespace PepperDash.Essentials
{
public class JoinedSigInterlock
{
public uint CurrentJoin { get; private set; }
BasicTriList TriList;
public BoolFeedback IsShownFeedback;
public event EventHandler<StatusChangedEventArgs> StatusChanged;
bool _IsShown;
public bool IsShown
{
get
{
return _IsShown;
}
private set
{
_IsShown = value;
IsShownFeedback.FireUpdate();
}
}
//public BoolFeedback ShownFeedback { get; private set; }
public JoinedSigInterlock(BasicTriList triList)
{
TriList = triList;
IsShownFeedback = new BoolFeedback(new Func<bool>( () => _IsShown));
}
/// <summary>
/// Hides CurrentJoin and shows join. Will check and re-set signal if join
/// equals CurrentJoin
/// </summary>
public void ShowInterlocked(uint join)
{
var prevJoin = CurrentJoin;
var wasShown = _IsShown;
//Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join);
if (CurrentJoin == join && TriList.BooleanInput[join].BoolValue)
return;
SetButDontShow(join);
TriList.SetBool(CurrentJoin, true);
IsShown = true;
OnStatusChange(prevJoin, CurrentJoin, wasShown, IsShown);
}
/// <summary>
///
/// </summary>
/// <param name="join"></param>
public void ShowInterlockedWithToggle(uint join)
{
var prevJoin = CurrentJoin;
var wasShown = IsShown;
//Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join);
if (CurrentJoin == join)
HideAndClear();
else
{
if (CurrentJoin > 0)
TriList.BooleanInput[CurrentJoin].BoolValue = false;
CurrentJoin = join;
TriList.BooleanInput[CurrentJoin].BoolValue = true;
IsShown = true;
OnStatusChange(prevJoin, CurrentJoin, wasShown, IsShown);
}
}
/// <summary>
/// Hides current join and clears CurrentJoin
/// </summary>
public void HideAndClear()
{
var prevJoin = CurrentJoin;
var wasShown = IsShown;
//Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin);
Hide();
CurrentJoin = 0;
OnStatusChange(prevJoin, CurrentJoin, wasShown, IsShown);
}
/// <summary>
/// Hides the current join but does not clear the selected join in case
/// it needs to be reshown
/// </summary>
public void Hide()
{
var prevJoin = CurrentJoin;
var wasShown = IsShown;
//Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin);
if (CurrentJoin > 0)
{
TriList.BooleanInput[CurrentJoin].BoolValue = false;
IsShown = false;
OnStatusChange(prevJoin, CurrentJoin, wasShown, IsShown);
}
}
/// <summary>
/// If CurrentJoin is set, it restores that join
/// </summary>
public void Show()
{
var prevJoin = CurrentJoin;
var wasShown = IsShown;
//Debug.Console(2, "Trilist {0:X2}, interlock showing {1}", TriList.ID, CurrentJoin);
if (CurrentJoin > 0)
{
TriList.BooleanInput[CurrentJoin].BoolValue = true;
IsShown = true;
OnStatusChange(prevJoin, CurrentJoin, wasShown, IsShown);
}
}
/// <summary>
/// Useful for pre-setting the interlock but not enabling it. Sets CurrentJoin
/// </summary>
/// <param name="join"></param>
public void SetButDontShow(uint join)
{
if (CurrentJoin > 0)
{
TriList.BooleanInput[CurrentJoin].BoolValue = false;
IsShown = false;
}
CurrentJoin = join;
}
void OnStatusChange(uint prevJoin, uint newJoin, bool wasShown, bool isShown)
{
var handler = StatusChanged;
if (handler != null)
handler(this, new StatusChangedEventArgs(prevJoin, newJoin, wasShown, isShown));
}
}
public class StatusChangedEventArgs : EventArgs
{
public uint PreviousJoin { get; set; }
public uint NewJoin { get; set; }
public bool WasShown { get; set; }
public bool IsShown { get; set; }
public StatusChangedEventArgs(uint prevJoin, uint newJoin, bool wasShown, bool isShown)
{
PreviousJoin = prevJoin;
NewJoin = newJoin;
WasShown = wasShown;
IsShown = isShown;
}
}
}

View File

@@ -1,55 +0,0 @@
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;
using PepperDash.Essentials.Core.SmartObjects;
namespace PepperDash.Essentials
{
/// <summary>
/// Very basic show/hide manager for weather page. Basic functionality is useful on any
/// size of interface
/// </summary>
public class SingleSubpageModalAndBackDriver : PanelDriverBase
{
BoolInputSig SubpageSig;
PanelDriverBase Parent;
public SingleSubpageModalAndBackDriver(PanelDriverBase parent, uint subpageJoin) : base(parent.TriList)
{
Parent = parent;
SubpageSig = Parent.TriList.BooleanInput[subpageJoin];
}
/// <summary>
/// This shows the driver.
/// Not sure I like this approach. Hides this and shows it's parent. Not really a navigation-stack type thing.
/// The parent is always the home page driver
/// </summary>
public override void Show()
{
SubpageSig.BoolValue = true;
base.Show();
}
public override void Hide()
{
SubpageSig.BoolValue = false;
base.Hide();
}
public override void BackButtonPressed()
{
Hide();
Parent.Show();
}
}
}

View File

@@ -1,43 +0,0 @@
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;
using PepperDash.Essentials.Core.SmartObjects;
namespace PepperDash.Essentials
{
/// <summary>
/// Very basic show/hide manager for weather page. Basic functionality is useful on any
/// size of interface
/// </summary>
public class SingleSubpageModalDriver : PanelDriverBase
{
BoolInputSig SubpageSig;
public SingleSubpageModalDriver(PanelDriverBase parent, uint subpageJoin, uint closeJoin)
: base(parent.TriList)
{
SubpageSig = parent.TriList.BooleanInput[subpageJoin];
parent.TriList.SetSigFalseAction(closeJoin, Hide);
}
public override void Show()
{
SubpageSig.BoolValue = true;
base.Show();
}
public override void Hide()
{
SubpageSig.BoolValue = false;
base.Hide();
}
}
}

View File

@@ -1,152 +0,0 @@
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
{
/// <summary>
/// Driver responsible for controlling the screenshaver showing the client logo, MC connection information and QR Code. Moves the elements around to prevent screen burn in
/// </summary>
public class ScreenSaverController : PanelDriverBase, IDisposable
{
/// <summary>
/// The parent driver for this
/// </summary>
private readonly EssentialsPanelMainInterfaceDriver _parent;
private JoinedSigInterlock PositionInterlock;
CTimer PositionTimer;
uint PositionTimeoutMs;
List<uint> PositionJoins;
int CurrentPositionIndex = 0;
public ScreenSaverController(EssentialsPanelMainInterfaceDriver parent, CrestronTouchpanelPropertiesConfig config)
: base(parent.TriList)
{
_parent = parent;
PositionTimeoutMs = config.ScreenSaverMovePositionIntervalMs;
PositionJoins = new List<uint>() { UIBoolJoin.MCScreenSaverPosition1Visible, UIBoolJoin.MCScreenSaverPosition2Visible, UIBoolJoin.MCScreenSaverPosition3Visible, UIBoolJoin.MCScreenSaverPosition4Visible };
PositionInterlock = new JoinedSigInterlock(parent.TriList);
var cmdName = String.Format("shwscrsvr-{0:X2}", parent.TriList.ID);
CrestronConsole.AddNewConsoleCommand((o) => Show(), cmdName, "Shows Panel Screensaver", ConsoleAccessLevelEnum.AccessOperator);
TriList.SetSigFalseAction(UIBoolJoin.MCScreenSaverClosePress, Hide);
}
public override void Show()
{
//Debug.Console(2, "Showing ScreenSaverController: {0:X2}", TriList.ID);
if (_parent.AvDriver != null)
{
_parent.AvDriver.PopupInterlock.ShowInterlocked(UIBoolJoin.MCScreenSaverVisible);
}
CurrentPositionIndex = 0;
ShowCurrentPosition();
StartPositionTimer();
base.Show();
}
public override void Hide()
{
//Debug.Console(2, "Hiding ScreenSaverController: {0:X2}", TriList.ID);
if (PositionTimer != null)
{
//Debug.Console(2, "Stopping PositionTimer: {0:X2}", TriList.ID);
PositionTimer.Stop();
PositionTimer.Dispose();
PositionTimer = null;
}
ClearAllPositions();
if (_parent.AvDriver != null)
{
_parent.AvDriver.PopupInterlock.HideAndClear();
}
base.Hide();
}
void StartPositionTimer()
{
//Debug.Console(2, "Starting Position Timer: {0:X2}", TriList.ID);
if (PositionTimer == null)
{
PositionTimer = new CTimer((o) => PositionTimerExpired(), PositionTimeoutMs);
}
else
{
PositionTimer.Reset(PositionTimeoutMs);
}
}
void PositionTimerExpired()
{
IncrementPositionIndex();
ShowCurrentPosition();
StartPositionTimer();
}
void IncrementPositionIndex()
{
if (CurrentPositionIndex < PositionJoins.Count - 1)
{
CurrentPositionIndex++;
}
else
{
CurrentPositionIndex = 0;
}
//Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0} ID: {1:X2}", CurrentPositionIndex, TriList.ID);
}
//
void ShowCurrentPosition()
{
// Set based on current index
PositionInterlock.ShowInterlocked(PositionJoins[CurrentPositionIndex]);
}
void ClearAllPositions()
{
//Debug.Console(2, "Hiding all screensaver positions: {0:X2}", TriList.ID);
PositionInterlock.HideAndClear();
}
#region IDisposable Members
public void Dispose()
{
Hide();
}
#endregion
}
}

View File

@@ -1,99 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials
{
/// <summary>
/// Used for interlocking sigs, using a set-clears-last-set model.
/// </summary>
public class SigInterlock
{
/// <summary>
///
/// </summary>
public BoolInputSig CurrentSig { get; private set; }
/// <summary>
///
/// </summary>
public SigInterlock()
{
}
/// <summary>
/// Hides CurrentJoin and shows join. Does nothing when resending CurrentJoin
/// </summary>
public void ShowInterlocked(BoolInputSig sig)
{
if (CurrentSig == sig)
return;
SetButDontShow(sig);
sig.BoolValue = true;
}
/// <summary>
///
/// </summary>
/// <param name="join"></param>
public void ShowInterlockedWithToggle(BoolInputSig sig)
{
if(CurrentSig == sig)
HideAndClear();
else
{
if(CurrentSig != null)
CurrentSig.BoolValue = false;
CurrentSig = sig;
CurrentSig.BoolValue = true;
}
}
/// <summary>
/// Hides current Sig and clears CurrentSig
/// </summary>
public void HideAndClear()
{
Hide();
CurrentSig = null;
}
/// <summary>
/// Hides the current Sig but does not clear the selected Sig in case
/// it needs to be reshown
/// </summary>
public void Hide()
{
if(CurrentSig != null)
CurrentSig.BoolValue = false;
}
/// <summary>
/// If CurrentSig is set, it restores that Sig
/// </summary>
public void Show()
{
if(CurrentSig != null)
CurrentSig.BoolValue = true;
}
/// <summary>
/// Useful for pre-setting the interlock but not enabling it. Sets CurrentSig
/// </summary>
/// <param name="join"></param>
public void SetButDontShow(BoolInputSig sig)
{
if (CurrentSig != null)
CurrentSig.BoolValue = false;
CurrentSig = sig;
}
}
}

View File

@@ -1,94 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.SmartObjects;
namespace PepperDash.Essentials
{
public class SmartObjectRoomsList : SmartObjectDynamicList
{
public uint StatusSigOffset { get; private set; }
List<SmartObjectRoomsListItem> Items;
public SmartObjectRoomsList(SmartObject so, uint nameSigOffset, uint statusSigOffset)
: base(so, true, nameSigOffset)
{
StatusSigOffset = statusSigOffset;
Items = new List<SmartObjectRoomsListItem>();
}
public void AddRoomItem(SmartObjectRoomsListItem item)
{
Items.Add(item);
}
public void SetItemStatusText(uint index, string text)
{
if (index > MaxCount) return;
// The list item template defines CIPS tags that refer to standard joins
(SmartObject.Device as BasicTriList).StringInput[StatusSigOffset + index].StringValue = text;
}
/// <summary>
/// Sets feedback for the given room
/// </summary>
public void SetFeedbackForRoom(IEssentialsHuddleSpaceRoom room)
{
var itemToSet = Items.FirstOrDefault(i => i.Room == room);
if (itemToSet != null)
SetFeedback(itemToSet.Index, true);
}
}
public class SmartObjectRoomsListItem
{
public IEssentialsHuddleSpaceRoom Room { get; private set; }
SmartObjectRoomsList Parent;
public uint Index { get; private set; }
public SmartObjectRoomsListItem(IEssentialsHuddleSpaceRoom room, uint index, SmartObjectRoomsList parent,
Action<bool> buttonAction)
{
Room = room;
Parent = parent;
Index = index;
if (room == null) return;
// Set "now" states
parent.SetItemMainText(index, room.Name);
UpdateItem(room.CurrentSourceInfo);
// Watch for later changes
room.CurrentSourceChange += new SourceInfoChangeHandler(room_CurrentSourceInfoChange);
parent.SetItemButtonAction(index, buttonAction);
}
void room_CurrentSourceInfoChange(SourceListItem info, ChangeType type)
{
UpdateItem(info);
}
/// <summary>
/// Helper to handle source events and startup syncing with room's current source
/// </summary>
/// <param name="info"></param>
void UpdateItem(SourceListItem info)
{
if (info == null || info.Type == eSourceListItemType.Off)
{
Parent.SetItemStatusText(Index, "");
Parent.SetItemIcon(Index, "Blank");
}
else
{
Parent.SetItemStatusText(Index, info.PreferredName);
Parent.SetItemIcon(Index, info.AltIcon);
}
}
}
}

View File

@@ -1,16 +0,0 @@
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
{
///// <summary>
///// The handler type for a Room's SourceInfoChange
///// </summary>
//public delegate void SourceInfoChangeHandler(IEssentialsRoom room, SourceListItem info, ChangeType type);
}

View File

@@ -1,158 +0,0 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials
{
public enum eAvSubpageType
{
NoControls,
PowerOff,
SetupFullDistributed,
SourceWaitOverlay,
TopBar,
VolumePopup,
ZoneSource
}
public enum eAvSourceSubpageType
{
AppleTv,
Radio,
Roku
}
public enum eCommonSubpageType
{
GenericModal,
Home,
PanelSetup,
Weather
}
public enum eAvSmartObjects
{
RoomList,
SourceList
}
public enum eCommonSmartObjects
{
HomePageList
}
/// <summary>
///
/// </summary>
public abstract class PanelDriverBase
{
/// <summary>
///
/// </summary>
public bool IsVisible { get; private set; }
public bool WasVisibleWhenHidden { get; private set; }
/// <summary>
/// Makes sure you call this.
/// Sets IsVisible and attaches back/home buttons to BackButtonPressed
/// </summary>
public virtual void Show()
{
IsVisible = true;
TriList.SetSigFalseAction(15002, BackButtonPressed);
}
/// <summary>
/// Will show if this was visible when Hide was called (for group hiding/showing)
/// </summary>
public void Restore()
{
if (WasVisibleWhenHidden)
Show();
}
/// <summary>
/// Only sets IsVisible
/// </summary>
public virtual void Hide()
{
WasVisibleWhenHidden = IsVisible;
IsVisible = false;
}
/// <summary>
/// Toggles visibility of this driver
/// </summary>
public virtual void Toggle()
{
if (IsVisible)
Hide();
else
Show();
}
/// <summary>
/// Override with specific back button behavior. Default is empty
/// </summary>
public virtual void BackButtonPressed()
{
}
public PanelDriverBase(BasicTriListWithSmartObject triList)
{
TriList = triList;
}
#region IBasicTriListWithSmartObject Members
/// <summary>
///
/// </summary>
public void AddSmartObjectHelper(uint id, object controller)
{
SmartObjectControllers.Add(id, controller);
}
/// <summary>
///
/// </summary>
public void RemoveSmartObjectHelper(uint id)
{
SmartObjectControllers.Remove(id);
}
Dictionary<uint, object> SmartObjectControllers = new Dictionary<uint, object>();
/// <summary>
/// The trilist object for the Crestron TP device
/// </summary>
public BasicTriListWithSmartObject TriList { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool ContainsSmartObjectHelper(uint id)
{
return SmartObjectControllers.ContainsKey(id);
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public object GetSmartObjectHelper(uint id)
{
if (SmartObjectControllers.ContainsKey(id))
return SmartObjectControllers[id];
else
return null;
}
#endregion
}
}