Compare commits

..

9 Commits

Author SHA1 Message Date
Andrew Welker
854a0691d3 Merge branch 'development' into feature/visca-presets-fix 2021-08-12 12:12:31 -06:00
Neil Dorin
61c638452b Merge pull request #775 from PepperDash/hotfix/zoom-camera-fixes
Hotfix/zoom camera fixes
2021-08-12 12:06:16 -06:00
Louis Iacovelli
072411e4f6 Added method to set preset for multiple situations 2021-08-12 11:49:59 -04:00
Andrew Welker
7dc9afa119 Merge branch 'development' into hotfix/zoom-camera-fixes 2021-08-11 11:47:48 -06:00
Jason T Alborough
6f0bfedac1 Merge branch 'main' into feature/visca-presets-fix 2021-08-11 13:31:06 -04:00
Jason Alborough
71881addab fix(Devices.Common.Cameras.CameraVisca): add and fire the event OnPresetsListHasChanged() after LinkToApi so that the camera presets populate to the bridge correctly 2021-08-11 13:00:51 -04:00
Neil Dorin
cea1d2fcdd Updates to mute toggle for ZoomRoom 2021-08-09 16:20:55 -06:00
Neil Dorin
22aea3089d #773 Adds some debug and sets the Capabilities value on ZoomRoomCamera
Also updates RunRouteAction in EssentialsHuddleVtc1Room to still call down in to main RunRouteAction method if called with a sourceListKey
2021-08-09 14:41:31 -06:00
Andrew Welker
43256acfcd Merge pull request #771 from PepperDash/hotfix/zoomroom-updates
Hotfix/zoomroom updates
2021-08-02 17:36:28 -06:00
22 changed files with 564 additions and 1535 deletions

View File

@@ -483,21 +483,18 @@ namespace PepperDash.Essentials
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
CreateMobileControlBridge(room);
CreateMobileControlBridge(room as EssentialsRoomBase);
}
else if (room is IEssentialsHuddleVtc1Room)
{
DeviceManager.AddDevice(room);
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));
}
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));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
CreateMobileControlBridge(room);
CreateMobileControlBridge(room as EssentialsRoomBase);
}
else if (room is EssentialsTechRoom)
{
@@ -509,7 +506,7 @@ namespace PepperDash.Essentials
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge");
CreateMobileControlBridge(room);
CreateMobileControlBridge(room as EssentialsRoomBase);
}
else
{
@@ -530,7 +527,7 @@ namespace PepperDash.Essentials
}
private static void CreateMobileControlBridge(IEssentialsRoom room)
private static void CreateMobileControlBridge(EssentialsRoomBase room)
{
var mobileControl = GetMobileControlDevice();

View File

@@ -144,7 +144,6 @@
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
<Compile Include="Room\Config\EssentialsTechRoomConfig.cs" />
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
<Compile Include="Room\Types\EssentialsCombinedHuddleVtc1Room.cs" />
<Compile Include="Room\Types\EssentialsDualDisplayRoom.cs" />
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
<Compile Include="Room\Types\EssentialsNDisplayRoomBase.cs" />

View File

@@ -39,10 +39,6 @@ namespace PepperDash.Essentials.Room.Config
{
return new EssentialsDualDisplayRoom(roomConfig);
}
if (typeName == "combinedhuddlevtc1")
{
return new EssentialsCombinedHuddleVtc1Room(roomConfig);
}
return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig);
}
@@ -187,12 +183,6 @@ namespace PepperDash.Essentials.Room.Config
[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();

View File

@@ -1,852 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using 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.Where((d) => d is DisplayBase) as List<DisplayBase>;
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 () =>
{
var displays = Displays.Where((d) => d is TwoWayDisplayBase) as List<TwoWayDisplayBase>;
if (displays != null)
{
var warmingDisplays = displays.Where((d) => d.IsWarmingUpFeedback.BoolValue);
if (warmingDisplays.Count() > 0)
{
return true;
}
else
return false;
}
else
return false;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () =>
{
var displays = Displays.Where((d) => d is TwoWayDisplayBase) as List<TwoWayDisplayBase>;
if (displays != null)
{
var coolingDisplays = displays.Where((d) => d.IsCoolingDownFeedback.BoolValue);
if (coolingDisplays.Count() > 0)
{
return true;
}
else
return false;
}
else
return false;
};
}
}
public EssentialsConferenceRoomPropertiesConfig 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<EssentialsConferenceRoomPropertiesConfig>
(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);
}
}
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];
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 += (o, a) =>
{
if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
//if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
// CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (dispTwoWay.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
};
}
display.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
IsWarmingUpFeedback.FireUpdate();
if (!IsWarmingUpFeedback.BoolValue)
(CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
};
display.IsCoolingDownFeedback.OutputChange += (o, a) =>
{
IsCoolingDownFeedback.FireUpdate();
};
}
}
}
private void SetSourceListKey()
{
if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey))
{
SetSourceListKey(PropertiesConfig.SourceListKey);
}
else
{
SetSourceListKey(Key);
}
SetCodecExternalSources();
}
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsConferenceRoomPropertiesConfig>(config.Properties.ToString());
if (newPropertiesConfig != null)
PropertiesConfig = newPropertiesConfig;
ConfigWriter.UpdateRoomConfig(config);
}
public override bool CustomActivate()
{
// 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);
return base.CustomActivate();
}
/// <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);
}
}
}
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

@@ -101,7 +101,7 @@ namespace PepperDash.Essentials
}
}
public EssentialsConferenceRoomPropertiesConfig PropertiesConfig { get; private set; }
public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; }
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
@@ -210,7 +210,7 @@ namespace PepperDash.Essentials
{
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
(config.Properties.ToString());
DefaultDisplay = DeviceManager.GetDeviceForKey((PropertiesConfig as EssentialsHuddleVtc1PropertiesConfig).DefaultDisplayKey) as IRoutingSinkWithSwitching;
DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
@@ -454,7 +454,8 @@ namespace PepperDash.Essentials
else
{
Debug.Console(1, this, "sourceListKey present but not yet implemented");
throw new NotImplementedException();
RunRouteAction(routeKey, new Action(() => { }));
}
}
@@ -471,7 +472,11 @@ namespace PepperDash.Essentials
RunRouteAction(routeKey, successCallback);
}
else
throw new NotImplementedException();
{
Debug.Console(1, this, "sourceListKey present but not yet implemented");
RunRouteAction(routeKey, successCallback);
}
}
/// <summary>

View File

@@ -10,9 +10,7 @@ namespace PepperDash.Essentials
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange,
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback
{
EssentialsConferenceRoomPropertiesConfig PropertiesConfig { get; }
bool ExcludeFromGlobalFunctions { get; }
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
void RunRouteAction(string routeKey);

View File

@@ -16,8 +16,6 @@ namespace PepperDash.Essentials
{
public class EssentialsTouchpanelController : EssentialsDevice, IHasBasicTriListWithSmartObject
{
private CrestronTouchpanelPropertiesConfig _propertiesConfig;
public BasicTriListWithSmartObject Panel { get; private set; }
public PanelDriverBase PanelDriver { get; private set; }
@@ -29,14 +27,7 @@ namespace PepperDash.Essentials
: base(key, name)
{
Panel = tsw;
if (!string.IsNullOrEmpty(sgdPath))
Panel.LoadSmartObjects(sgdPath);
else
Debug.Console(1, this, "No SGD file path defined");
tsw.LoadSmartObjects(sgdPath);
tsw.SigChange += Panel_SigChange;
}
@@ -46,7 +37,7 @@ namespace PepperDash.Essentials
Panel = dge;
if (!string.IsNullOrEmpty(sgdPath))
Panel.LoadSmartObjects(sgdPath);
dge.LoadSmartObjects(sgdPath);
else
Debug.Console(1, this, "No SGD file path defined");
@@ -59,7 +50,6 @@ namespace PepperDash.Essentials
public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
: base(key, name)
{
_propertiesConfig = props;
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware...");
type = type.ToLower();
@@ -71,8 +61,6 @@ namespace PepperDash.Essentials
app.ParameterProjectName.Value = props.ProjectName;
Panel = app;
}
else if (type == "xpanel")
Panel = new XpanelForSmartGraphics(id, Global.ControlSystem);
else if (type == "tsw550")
Panel = new Tsw550(id, Global.ControlSystem);
else if (type == "tsw552")
@@ -146,194 +134,10 @@ namespace PepperDash.Essentials
Panel.LoadSmartObjects(sgdName);
Panel.SigChange += Panel_SigChange;
AddPostActivationAction(() =>
{
// Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event
var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner;
if (roomCombiner != null)
{
// Subscribe to the even
roomCombiner.RoomCombinationScenarioChanged += new EventHandler<EventArgs>(roomCombiner_RoomCombinationScenarioChanged);
// Connect to the initial roomKey
if (roomCombiner.CurrentScenario != null)
{
// Use the current scenario
DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario);
}
else
{
// Current Scenario not yet set. Use default
SetupPanelDrivers(_propertiesConfig.DefaultRoomKey);
}
}
else
{
// No room combiner, use the default key
SetupPanelDrivers(_propertiesConfig.DefaultRoomKey);
}
});
}
void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e)
{
var roomCombiner = sender as IEssentialsRoomCombiner;
DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario);
}
/// <summary>
/// Determines the room key to use based on the scenario
/// </summary>
/// <param name="scenario"></param>
void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario)
{
string newRoomKey = null;
if (scenario.UiMap.ContainsKey(Key))
{
newRoomKey = scenario.UiMap[Key];
}
else if (scenario.UiMap.ContainsKey(_propertiesConfig.DefaultRoomKey))
{
newRoomKey = scenario.UiMap[_propertiesConfig.DefaultRoomKey];
}
SetupPanelDrivers(newRoomKey);
}
/// <summary>
/// Sets up drivers and links them to the room specified
/// </summary>
/// <param name="roomKey">key of room to link the drivers to</param>
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, _propertiesConfig);
// 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, _propertiesConfig);
// Header Driver
Debug.Console(0, this, "Adding header driver");
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig);
// AV Driver
Debug.Console(0, this, "Adding huddle space AV driver");
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, _propertiesConfig);
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, _propertiesConfig);
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, _propertiesConfig);
// Header Driver
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig);
// AV Driver
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, _propertiesConfig);
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, _propertiesConfig);
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();
}
@@ -344,6 +148,7 @@ namespace PepperDash.Essentials
PanelDriver.BackButtonPressed();
}
void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
{
// If the sig is transitioning on, mark it in case it was home button that transitioned it
@@ -420,6 +225,119 @@ namespace PepperDash.Essentials
var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, dc.Type, props, comm.IpIdInt);
panelController.AddPostActivationAction(() =>
{
var mainDriver = new EssentialsPanelMainInterfaceDriver(panelController.Panel, props);
// Then the sub drivers
// spin up different room drivers depending on room type
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
if (room is IEssentialsHuddleSpaceRoom)
{
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props);
// Header Driver
Debug.Console(0, panelController, "Adding header driver");
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
// AV Driver
Debug.Console(0, panelController, "Adding huddle space AV driver");
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
avDriver.DefaultRoomKey = props.DefaultRoomKey;
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, panelController, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
if (panelController.Panel is TswFt5ButtonSystem)
{
var tsw = panelController.Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
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, panelController, "Adding huddle space VTC AV driver");
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props);
// Header Driver
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
// AV Driver
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props);
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(panelController.Panel, avDriver,
(room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver);
avDriver.SetVideoCodecDriver(codecDriver);
avDriver.DefaultRoomKey = props.DefaultRoomKey;
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, panelController, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
if (panelController.Panel is TswFt5ButtonSystem)
{
var tsw = panelController.Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.EndMeetingPress(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
}
else
{
Debug.Console(0, panelController, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
}
});
return panelController;
}
}

View File

@@ -11,7 +11,7 @@ namespace PepperDash.Essentials
/// <summary>
///
/// </summary>
public class EssentialsPanelMainInterfaceDriver : PanelDriverBase, IHasScreenSaverController, IDisposable
public class EssentialsPanelMainInterfaceDriver : PanelDriverBase, IHasScreenSaverController
{
CTimer InactivityTimer;
@@ -69,35 +69,6 @@ namespace PepperDash.Essentials
}
}
#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)
{
@@ -159,7 +130,7 @@ namespace PepperDash.Essentials
if(CurrentChildDriver != null)
CurrentChildDriver.BackButtonPressed();
}
}
}
public interface IHasScreenSaverController
{

View File

@@ -306,7 +306,7 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{
if (CurrentRoom != null && CurrentRoom.DefaultDisplay != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
(CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
});

View File

@@ -1,326 +1,326 @@
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 (StatusListDeviceIndexes.ContainsKey(c))
{
var i = StatusListDeviceIndexes[c];
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)e.Status;
}
}
}
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

@@ -319,7 +319,7 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{
if (CurrentRoom != null && CurrentRoom.DefaultDisplay != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
(CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
});
@@ -448,7 +448,7 @@ namespace PepperDash.Essentials
// and the LastMeetingDismissed != this meeting
var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId);
Debug.Console(1, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
CurrentRoom.OnFeedback.BoolValue,
LastMeetingDismissedId,
lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToShortTimeString() : "");

View File

@@ -12,7 +12,7 @@ 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
public class ScreenSaverController : PanelDriverBase
{
/// <summary>
@@ -42,7 +42,7 @@ namespace PepperDash.Essentials
PositionInterlock = new JoinedSigInterlock(parent.TriList);
var cmdName = String.Format("shwscrsvr-{0:X2}", parent.TriList.ID);
var cmdName = String.Format("shwscrsvr-{0}", parent.TriList.ID);
CrestronConsole.AddNewConsoleCommand((o) => Show(), cmdName, "Shows Panel Screensaver", ConsoleAccessLevelEnum.AccessOperator);
@@ -51,8 +51,6 @@ namespace PepperDash.Essentials
public override void Show()
{
Debug.Console(2, "Showing ScreenSaverController: {0:X2}", TriList.ID);
if (_parent.AvDriver != null)
{
_parent.AvDriver.PopupInterlock.ShowInterlocked(UIBoolJoin.MCScreenSaverVisible);
@@ -67,11 +65,10 @@ namespace PepperDash.Essentials
public override void Hide()
{
Debug.Console(2, "Hiding ScreenSaverController: {0:X2}", TriList.ID);
Debug.Console(1, "Hiding ScreenSaverController");
if (PositionTimer != null)
{
Debug.Console(2, "Stopping PositionTimer: {0:X2}", TriList.ID);
PositionTimer.Stop();
PositionTimer.Dispose();
PositionTimer = null;
@@ -89,8 +86,6 @@ namespace PepperDash.Essentials
void StartPositionTimer()
{
Debug.Console(2, "Starting Position Timer: {0:X2}", TriList.ID);
if (PositionTimer == null)
{
PositionTimer = new CTimer((o) => PositionTimerExpired(), PositionTimeoutMs);
@@ -122,7 +117,7 @@ namespace PepperDash.Essentials
CurrentPositionIndex = 0;
}
Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0} ID: {1:X2}", CurrentPositionIndex, TriList.ID);
Debug.Console(1, "ScreenSaver Position Timer Expired: Setting new position: {0}", CurrentPositionIndex);
}
//
@@ -134,19 +129,9 @@ namespace PepperDash.Essentials
void ClearAllPositions()
{
Debug.Console(2, "Hiding all screensaver positions: {0:X2}", TriList.ID);
Debug.Console(1, "Hiding all screensaver positions");
PositionInterlock.HideAndClear();
}
#region IDisposable Members
public void Dispose()
{
Hide();
}
#endregion
}
}

View File

@@ -782,12 +782,14 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (camerasCodec != null && camerasCodec.SelectedCamera != null)
{
Debug.Console(2, "Attempting to map camera actions to selected camera: '{0}'", camerasCodec.SelectedCamera.Key);
var dpad = CameraPtzPad;
var camera = camerasCodec.SelectedCamera as IHasCameraPtzControl;
if (camera != null)
{
Debug.Console(2, "Selected camera is IHasCameraPtzControl");
if (camerasCodec.SelectedCamera.CanTilt)
{
dpad.SigUp.SetBoolSigAction((b) =>
@@ -852,6 +854,14 @@ namespace PepperDash.Essentials.UIDrivers.VC
}
}
else
{
Debug.Console(2, "Selected Camera is not IHasCameraPtzControl. No controls to map");
}
}
else
{
Debug.Console(2, "Codec does not have cameras of selected camera is null");
}
}

View File

@@ -8,7 +8,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
/// </summary>
public interface IMobileControl : IKeyed
{
void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent);
void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent);
void LinkSystemMonitorToAppServer();
}

View File

@@ -54,20 +54,13 @@ namespace PepperDash.Essentials.Core
SetupPartitionStateProviders();
SetRooms();
if (isInAutoMode)
{
DetermineRoomCombinationScenario();
}
else
{
SetRoomCombinationScenario(_propertiesConfig.defaultScenarioKey);
}
});
}
void CreateScenarios()
{
RoomCombinationScenarios = new List<IRoomCombinationScenario>();
foreach (var scenarioConfig in _propertiesConfig.Scenarios)
{
var scenario = new RoomCombinationScenario(scenarioConfig);
@@ -167,7 +160,7 @@ namespace PepperDash.Essentials.Core
{
return _currentScenario;
}
private set
set
{
if (value != _currentScenario)
{
@@ -227,11 +220,9 @@ namespace PepperDash.Essentials.Core
// Get the scenario
var scenario = RoomCombinationScenarios.FirstOrDefault((s) => s.Key.Equals(scenarioKey));
// Set the parition states from the scenario manually
if (scenario != null)
{
Debug.Console(0, this, "Manually setting scenario to '{0}'", scenario.Key);
foreach (var partitionState in scenario.PartitionStates)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
@@ -240,25 +231,15 @@ namespace PepperDash.Essentials.Core
{
if (partitionState.PartitionPresent)
{
Debug.Console(0, this, "Manually setting state to Present for: '{0}'", partition.Key);
partition.SetPartitionStatePresent();
}
else
{
Debug.Console(0, this, "Manually setting state to Not Present for: '{0}'", partition.Key);
partition.SetPartitionStateNotPresent();
}
}
else
{
Debug.Console(1, this, "Unable to find partition with key: '{0}'", partitionState.PartitionKey);
}
}
}
else
{
Debug.Console(1, this, "Unable to find scenario with key: '{0}'", scenarioKey);
}
}
#endregion

View File

@@ -30,7 +30,7 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// The list of rooms keys that can be combined
/// </summary>
[JsonProperty("roomKeys")]
[JsonProperty("roomMap")]
public List<string> RoomKeys {get; set;}
/// <summary>
@@ -87,9 +87,6 @@ namespace PepperDash.Essentials.Core
[JsonProperty("partitionStates")]
public List<PartitionState> PartitionStates { get; set; }
/// <summary>
/// Determines which UI devices get mapped to which room in this scenario. The Key should be the key of the UI device and the Value should be the key of the room to map to
/// </summary>
[JsonProperty("uiMap")]
public Dictionary<string, string> UiMap { get; set; }

View File

@@ -206,27 +206,6 @@ namespace PepperDash.Essentials.Core
return ClearSigAction(tl.StringOutput[sigNum]) as StringOutputSig;
}
/// <summary>
/// Clears all actions on all sigs
/// </summary>
public static void ClearAllSigActions(this BasicTriList t1)
{
foreach (var sig in t1.BooleanOutput)
{
ClearSigAction(sig);
}
foreach (var sig in t1.UShortOutput)
{
ClearSigAction(sig);
}
foreach (var sig in t1.StringOutput)
{
ClearSigAction(sig);
}
}
/// <summary>
/// Helper method to set the value of a bool Sig on TriList
/// </summary>

View File

@@ -216,21 +216,11 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
var presetsCamera = cameraDevice as IHasCameraPresets;
presetsCamera.PresetsListHasChanged += new EventHandler<EventArgs>((o, a) =>
{
for (int i = 1; i <= joinMap.NumberOfPresets.JoinNumber; i++)
{
int tempNum = i - 1;
string label = "";
var preset = presetsCamera.Presets.FirstOrDefault(p => p.ID.Equals(i));
if (preset != null)
label = preset.Description;
trilist.SetString((ushort) (joinMap.PresetLabelStart.JoinNumber + tempNum), label);
}
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
});
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
for (int i = 0; i < joinMap.NumberOfPresets.JoinNumber; i++)
{
int tempNum = i;
@@ -246,10 +236,35 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
presetsCamera.PresetStore(tempNum, label);
});
}
trilist.OnlineStatusChange += (sender, args) =>
{
if (!args.DeviceOnLine)
{ return; }
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
};
}
}
private void SendCameraPresetNamesToApi(IHasCameraPresets presetsCamera, CameraControllerJoinMap joinMap, BasicTriList trilist)
{
for (int i = 1; i <= joinMap.NumberOfPresets.JoinNumber; i++)
{
int tempNum = i - 1;
string label = "";
var preset = presetsCamera.Presets.FirstOrDefault(p => p.ID.Equals(i));
if (preset != null)
label = preset.Description;
trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label);
}
}
}
public class CameraPreset : PresetBase
{
public CameraPreset(int id, string description, bool isDefined, bool isDefinable)

View File

@@ -170,6 +170,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge);
//OnPresetsListHasChanged();
}
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
@@ -525,6 +528,15 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public event EventHandler<EventArgs> PresetsListHasChanged;
protected void OnPresetsListHasChanged()
{
var handler = PresetsListHasChanged;
if (handler == null)
return;
handler.Invoke(this, EventArgs.Empty);
}
public List<CameraPreset> Presets { get; private set; }
public void PresetSelect(int preset)
@@ -537,6 +549,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
SavePreset(preset);
}
#endregion
#region IHasCameraFocusControl Members

View File

@@ -1,17 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Displays
{
public interface IInputHdmi1 { void InputHdmi1(); }
public interface IInputHdmi2 { void InputHdmi2(); }
public interface IInputHdmi3 { void InputHdmi3(); }
public interface IInputHdmi4 { void InputHdmi4(); }
public interface IInputDisplayPort1 { void InputDisplayPort1(); }
public interface IInputDisplayPort2 { void InputDisplayPort2(); }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Displays
{
public interface IInputHdmi1 { void InputHdmi1(); }
public interface IInputHdmi2 { void InputHdmi2(); }
public interface IInputHdmi3 { void InputHdmi3(); }
public interface IInputHdmi4 { void InputHdmi4(); }
public interface IInputDisplayPort1 { void InputDisplayPort1(); }
public interface IInputDisplayPort2 { void InputDisplayPort2(); }
public interface IInputVga1 { void InputVga1(); }
}

View File

@@ -157,7 +157,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
get
{
return () => CrestronEnvironment.ScaleWithLimits(Configuration.Audio.Output.Volume, 100, 0, 65535, 0);
return () =>
{
var scaledVol = CrestronEnvironment.ScaleWithLimits(Configuration.Audio.Output.Volume, 100, 0, 65535, 0);
if (Configuration.Audio.Output.Volume != 0)
{
Debug.Console(2, this, "Storing previous volume level as: {0}, scaled: {1}", Configuration.Audio.Output.Volume, scaledVol);
_previousVolumeLevel = scaledVol; // Store the previous level for recall
}
return scaledVol;
};
}
}
@@ -281,7 +292,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var handler = CameraSelected;
if (handler != null)
{
handler(this, new CameraSelectedEventArgs(SelectedCamera));
handler(this, new CameraSelectedEventArgs(_selectedCamera));
}
}
}
@@ -1693,12 +1704,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public override void MuteOff()
{
Debug.Console(2, this, "Unmuting to previous level: {0}", _previousVolumeLevel);
SetVolume((ushort)_previousVolumeLevel);
}
public override void MuteOn()
{
_previousVolumeLevel = Configuration.Audio.Output.Volume; // Store the previous level for recall
SetVolume(0);
}
@@ -2024,6 +2035,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
foreach (var cam in Status.Cameras)
{
// Known Issue:
// Crestron UC engine systems seem to report an item in the cameras list that represnts the USB bridge device.
// If we know the name and it's reliably consistent, we could ignore it here...
if (cam.Name.IndexOf("HD-CONV-USB") > -1)
{
// Skip this as it's the Crestron USB box, not a real camera
continue;
}
var camera = new ZoomRoomCamera(cam.id, cam.Name, this);
Cameras.Add(camera);

View File

@@ -63,6 +63,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
: base(key, name)
{
ParentCodec = codec;
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom;
}
/// <summary>