From 537c6a42ffebbdb573bc5b19609bdd0baf6f0df1 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Wed, 1 Jul 2020 19:31:12 -0600 Subject: [PATCH] modify VTC1 room class to work with modified base class --- .../Rooms/Types/EssentialsHuddleVtc1Room.cs | 601 +++++------------- 1 file changed, 166 insertions(+), 435 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Rooms/Types/EssentialsHuddleVtc1Room.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Rooms/Types/EssentialsHuddleVtc1Room.cs index 28638937..bf544bae 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Rooms/Types/EssentialsHuddleVtc1Room.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Rooms/Types/EssentialsHuddleVtc1Room.cs @@ -1,9 +1,5 @@ using System; -using System.Linq; -using Crestron.SimplSharp; - using Newtonsoft.Json; - using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; @@ -16,85 +12,42 @@ using PepperDash.Essentials.Core.Rooms.Config; namespace PepperDash.Essentials { public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange, - IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback - { - public event EventHandler CurrentVolumeDeviceChange; - public event SourceInfoChangeHandler CurrentSourceChange; - - - //************************ - // Call-related stuff - - public BoolFeedback InCallFeedback { get; private set; } - - ///// - ///// Make this more specific - ///// - //public List ActiveCalls { get; private set; } - - /// - /// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis - /// - public IntFeedback CallTypeFeedback { get; private set; } - - /// - /// - /// - public BoolFeedback PrivacyModeIsOnFeedback { get; private set; } - - /// - /// When something in the room is sharing with the far end or through other means - /// - public BoolFeedback IsSharingFeedback { get; private set; } - - //************************ - - public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; } - - public VideoCodecBase VideoCodec { get; private set; } - - public AudioCodecBase AudioCodec { get; private set; } - - /// - /// If room is off, enables power on to last source. Default true - /// - - private string _lastSourceKey; - + IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, + IHasDefaultDisplay, IHasInCallFeedback + { /// /// "codecOsd" /// - public string DefaultCodecRouteString { get { return "codecOsd"; } } + public const string DefaultCodecRouteString = "codecOsd"; - /// - /// Temporary implementation. Returns the schedule-ready object or null if none. Fow now, - /// always returns the VideoCodec if it is capable - /// - public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } } - - private readonly CCriticalSection _sourceSelectLock = new CCriticalSection(); + private EssentialsHuddleVtc1PropertiesConfig _propertiesConfig; public EssentialsHuddleVtc1Room(DeviceConfig config) : base(config) { try { - PropertiesConfig = JsonConvert.DeserializeObject + _propertiesConfig = JsonConvert.DeserializeObject (config.Properties.ToString()); - DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; + DefaultDisplay = + DeviceManager.GetDeviceForKey(_propertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; - VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as + VideoCodec = DeviceManager.GetDeviceForKey(_propertiesConfig.VideoCodecKey) as VideoCodecBase; if (VideoCodec == null) + { throw new ArgumentNullException("codec cannot be null"); + } - AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as + AudioCodec = DeviceManager.GetDeviceForKey(_propertiesConfig.AudioCodecKey) as AudioCodecBase; if (AudioCodec == null) + { Debug.Console(0, this, "No Audio Codec Found"); + } - DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IRoutingSink; + DefaultAudioDevice = DeviceManager.GetDeviceForKey(_propertiesConfig.DefaultAudioKey) as IRoutingSink; Initialize(); } @@ -104,14 +57,92 @@ namespace PepperDash.Essentials } } - void Initialize() - { + /// + /// Temporary implementation. Returns the schedule-ready object or null if none. Fow now, + /// always returns the VideoCodec if it is capable + /// + public IHasScheduleAwareness ScheduleSource + { + get { return VideoCodec as IHasScheduleAwareness; } + } + + #region IHasAudioCodec Members + + public AudioCodecBase AudioCodec { get; private set; } + + #endregion + + #region IHasVideoCodec Members + + public BoolFeedback InCallFeedback { get; private set; } + + + /// + /// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis + /// + public IntFeedback CallTypeFeedback { get; private set; } + + /// + /// When something in the room is sharing with the far end or through other means + /// + public BoolFeedback IsSharingFeedback { get; private set; } + + //************************ + + public VideoCodecBase VideoCodec { get; private set; } + + #endregion + + #region IPrivacy Members + + /// + /// + /// + public BoolFeedback PrivacyModeIsOnFeedback { get; private set; } + + public void PrivacyModeOff() + { + VideoCodec.PrivacyModeOff(); + } + + public void PrivacyModeOn() + { + VideoCodec.PrivacyModeOn(); + } + + public void PrivacyModeToggle() + { + VideoCodec.PrivacyModeToggle(); + } + + #endregion + + #region IRunDefaultCallRoute Members + + /// + /// Sets up the room when started into call mode without presenting a source + /// + /// + public bool RunDefaultCallRoute() + { + RunRouteAction(DefaultCodecRouteString); + return true; + } + + #endregion + + private void Initialize() + { try { if (DefaultAudioDevice != null) + { DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; + } else if (DefaultAudioDevice is IHasVolumeDevice) + { DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; + } CurrentVolumeControls = DefaultVolumeControls; @@ -122,21 +153,25 @@ namespace PepperDash.Essentials var inVideoCall = false; if (AudioCodec != null) + { inAudioCall = AudioCodec.IsInCall; + } if (VideoCodec != null) + { inVideoCall = VideoCodec.IsInCall; + } return inAudioCall || inVideoCall; }); // Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback - MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); + MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(_propertiesConfig, this); Debug.Console(2, this, "Microphone Privacy Config evaluated."); // Get emergency object, if any - Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); + Emergency = EssentialsRoomConfigHelper.GetEmergency(_propertiesConfig, this); Debug.Console(2, this, "Emergency Config evaluated."); @@ -144,7 +179,9 @@ namespace PepperDash.Essentials VideoCodec.CallStatusChange += (o, a) => InCallFeedback.FireUpdate(); if (AudioCodec != null) + { AudioCodec.CallStatusChange += (o, a) => InCallFeedback.FireUpdate(); + } IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => IsSharingFeedback.FireUpdate(); @@ -167,14 +204,69 @@ namespace PepperDash.Essentials OnFeedbackFunc = () => CurrentSourceInfo != null && CurrentSourceInfo.Type == eSourceListItemType.Route; + IsWarmingFeedbackFunc = () => disp.IsWarmingUpFeedback.BoolValue; + IsCoolingFeedbackFunc = () => disp.IsCoolingDownFeedback.BoolValue; + InitializeDisplay(disp); - } catch (Exception e) { Debug.Console(0, this, "Error Initializing Room: {0}", e); } - } + } + + protected override void CustomSetConfig(DeviceConfig config) + { + var newPropertiesConfig = + JsonConvert.DeserializeObject(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"); + SetRoomOccupancy(DeviceManager.GetDeviceForKey(_propertiesConfig.Occupancy.DeviceKey) as + IOccupancyStatusProvider, _propertiesConfig.Occupancy.TimeoutMinutes); + } + + LogoUrl = _propertiesConfig.Logo.GetUrl(); + SourceListKey = _propertiesConfig.SourceListKey; + DefaultSourceItem = _propertiesConfig.DefaultSourceItem; + DefaultVolume = (ushort) (_propertiesConfig.Volumes.Master.Level*65535/100); + + return base.CustomActivate(); + } + + + /// + /// + /// + protected override void EndShutdown() + { + VideoCodec.EndAllCalls(); + + if (AudioCodec != null) + { + AudioCodec.EndAllCalls(); + } + + base.EndShutdown(); + } + + + public override void RoomVacatedForTimeoutPeriod(object o) + { + //Implement this + } #region Overrides of EssentialsRoomBase @@ -182,12 +274,17 @@ namespace PepperDash.Essentials { var disp = sender as DisplayBase; - if (disp == null) return; + if (disp == null) + { + return; + } if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) { if (!disp.PowerIsOnFeedback.BoolValue) + { CurrentSourceInfo = null; + } OnFeedback.FireUpdate(); } if (disp.PowerIsOnFeedback.BoolValue) @@ -217,372 +314,6 @@ namespace PepperDash.Essentials } } - - #endregion - - protected override void CustomSetConfig(DeviceConfig config) - { - var newPropertiesConfig = JsonConvert.DeserializeObject(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"); - SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as - IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); - } - - LogoUrl = PropertiesConfig.Logo.GetUrl(); - SourceListKey = PropertiesConfig.SourceListKey; - DefaultSourceItem = PropertiesConfig.DefaultSourceItem; - DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); - - return base.CustomActivate(); - } - - - /// - /// - /// - protected override void EndShutdown() - { - VideoCodec.EndAllCalls(); - - SetDefaultLevels(); - - RunDefaultPresentRoute(); - - CrestronEnvironment.Sleep(1000); - - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room"); - - RunRouteAction("roomOff"); - } - - /// - /// Routes the default source item, if any. Returns true when default route exists - /// - public override bool RunDefaultPresentRoute() - { - if (DefaultSourceItem != null) - RunRouteAction(DefaultSourceItem); - - return DefaultSourceItem != null; - } - - /// - /// Sets up the room when started into call mode without presenting a source - /// - /// - public bool RunDefaultCallRoute() - { - RunRouteAction(DefaultCodecRouteString); - return true; - } - - /// - /// - /// - /// - public override void RunRouteAction(string routeKey) - { - RunRouteAction(routeKey, () => { }); - } - - /// - /// - /// - /// - /// - public void RunRouteAction(string routeKey, string souceListKey) - { - throw new NotImplementedException(); - } - - /// - /// - /// - /// - /// - /// - public void RunRouteAction(string routeKey, string souceListKey, Action successCallback) - { - throw new NotImplementedException(); - } - - /// - /// Gets a source from config list SourceListKey and dynamically build and executes the - /// route or commands - /// - public void RunRouteAction(string routeKey, Action successCallback) - { - // Run this on a separate thread - //new CTimer - CrestronInvoke.BeginInvoke(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; - var 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(); - - // 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 - } - - /// - /// - /// - /// - 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); - } - - /// - /// - /// - /// - /// - private bool DoRoute(SourceRouteListItem route) - { - IRoutingSink dest; - - if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase)) - dest = DefaultAudioDevice as IRoutingSinkNoSwitching; - else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) - dest = DefaultDisplay; - else - dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching; - - if (dest == null) - { - Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey); - return false; - } - - if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) - { - dest.ReleaseRoute(); - if (dest is IPower) - (dest as IPower).PowerOff(); - } - else - { - var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs; - if (source == null) - { - Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey); - return false; - } - dest.ReleaseAndMakeRoute(source, route.Type); - } - return true; - } - - public override void RoomVacatedForTimeoutPeriod(object o) - { - //Implement this - } - - /// - /// Does what it says - /// - public override void SetDefaultLevels() - { - Debug.Console(1, this, "Restoring default levels"); - var vc = CurrentVolumeControls as IBasicVolumeWithFeedback; - if (vc != null) - vc.SetVolume(DefaultVolume); - } - /// - /// Will power the room on with the last-used source - /// - public override void PowerOnToDefaultOrLastSource() - { - if (!EnablePowerOnToLastSource || _lastSourceKey == null) - return; - RunRouteAction(_lastSourceKey); - } - - /// - /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions - /// - public static void AllRoomsOff() - { - var allRooms = DeviceManager.AllDevices.Where(d => - d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions); - foreach (var room in allRooms) - { - var essentialsHuddleSpaceRoom = room as EssentialsHuddleSpaceRoom; - if (essentialsHuddleSpaceRoom != null) - { - essentialsHuddleSpaceRoom.RunRouteAction("roomOff"); - } - } - } - - #region IPrivacy Members - - - public void PrivacyModeOff() - { - VideoCodec.PrivacyModeOff(); - } - - public void PrivacyModeOn() - { - VideoCodec.PrivacyModeOn(); - } - - public void PrivacyModeToggle() - { - VideoCodec.PrivacyModeToggle(); - } - #endregion } } \ No newline at end of file