Merge branch 'release/1.10.0' into feature/add-cisco-room-kit-features

This commit is contained in:
Neil Dorin 2022-02-15 16:05:14 -07:00
commit 428edad38a
72 changed files with 3631 additions and 980 deletions

Binary file not shown.

View file

@ -506,8 +506,11 @@ namespace PepperDash.Essentials
{ {
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId); if (!(room is EssentialsCombinedHuddleVtc1Room))
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..."); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");

View file

@ -88,7 +88,7 @@
{ {
"name": "Wireless Video", "name": "Wireless Video",
"key": "wePresent-1", "key": "wePresent-1",
"type": "wePresent", "type": "genericSource",
"group": "genericSource", "group": "genericSource",
"uid": 9, "uid": 9,
"properties": { "properties": {

View file

@ -114,7 +114,7 @@
{ {
"name": "Wireless Video", "name": "Wireless Video",
"key": "wePresent-1", "key": "wePresent-1",
"type": "wePresent", "type": "genericSource",
"properties": {}, "properties": {},
"group": "genericSource", "group": "genericSource",
"uid": 3 "uid": 3

View file

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

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ControlSystem> <ControlSystem>
<Name>192.168.10.1</Name> <Name>Test RMC3</Name>
<Address>auto 192.168.10.1</Address> <Address>auto 192.168.1.40;username crestron</Address>
<ProgramSlot>Program01</ProgramSlot> <ProgramSlot>Program01</ProgramSlot>
<Storage>Internal Flash</Storage> <Storage>Internal Flash</Storage>
</ControlSystem> </ControlSystem>

View file

@ -39,6 +39,10 @@ namespace PepperDash.Essentials.Room.Config
{ {
return new EssentialsDualDisplayRoom(roomConfig); return new EssentialsDualDisplayRoom(roomConfig);
} }
if (typeName == "combinedhuddlevtc1")
{
return new EssentialsCombinedHuddleVtc1Room(roomConfig);
}
return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig); return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig);
} }
@ -147,6 +151,24 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("helpMessage")] [JsonProperty("helpMessage")]
public string HelpMessage { get; set; } 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")] [JsonProperty("environment")]
public EssentialsEnvironmentPropertiesConfig Environment { get; set; } public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
@ -183,6 +205,12 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")] [JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; } 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() public EssentialsRoomPropertiesConfig()
{ {
LogoLight = new EssentialsLogoPropertiesConfig(); LogoLight = new EssentialsLogoPropertiesConfig();

View file

@ -56,6 +56,9 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("mirroredTuners")] [JsonProperty("mirroredTuners")]
public Dictionary<uint, string> MirroredTuners { get; set; } public Dictionary<uint, string> MirroredTuners { get; set; }
[JsonProperty("helpMessage")]
public string HelpMessage { get; set; }
/// <summary> /// <summary>
/// Indicates the room /// Indicates the room
/// </summary> /// </summary>

View file

@ -0,0 +1,821 @@
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.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);
}
}
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<EssentialsHuddleVtc1PropertiesConfig>(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

@ -202,11 +202,28 @@ namespace PepperDash.Essentials
}; };
} }
SetupEnvironmentalControlDevices();
SetSourceListKey(); SetSourceListKey();
EnablePowerOnToLastSource = true; 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() private void SetSourceListKey()
{ {
if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey)) if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey))

View file

@ -210,21 +210,29 @@ namespace PepperDash.Essentials
{ {
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig> PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
(config.Properties.ToString()); (config.Properties.ToString());
DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; DefaultDisplay = DeviceManager.GetDeviceForKey((PropertiesConfig as EssentialsHuddleVtc1PropertiesConfig).DefaultDisplayKey) as IRoutingSinkWithSwitching;
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase; PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null) if (VideoCodec == null)
throw new ArgumentNullException("codec cannot be 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 AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase; PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null) if (AudioCodec == null)
Debug.Console(0, this, "No Audio Codec Found"); Debug.Console(0, this, "No Audio Codec Found");
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls; 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");
}
InitializeRoom(); InitializeRoom();
} }
@ -326,6 +334,8 @@ namespace PepperDash.Essentials
CallTypeFeedback = new IntFeedback(() => 0); CallTypeFeedback = new IntFeedback(() => 0);
SetupEnvironmentalControlDevices();
SetSourceListKey(); SetSourceListKey();
EnablePowerOnToLastSource = true; EnablePowerOnToLastSource = true;
@ -336,6 +346,21 @@ namespace PepperDash.Essentials
} }
} }
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() private void SetSourceListKey()
{ {
@ -419,6 +444,14 @@ namespace PepperDash.Essentials
/// <returns></returns> /// <returns></returns>
public bool RunDefaultCallRoute() 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); RunRouteAction(DefaultCodecRouteString);
return true; return true;
} }

View file

@ -19,7 +19,7 @@ namespace PepperDash.Essentials
{ {
public class EssentialsTechRoom : EssentialsRoomBase, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction public class EssentialsTechRoom : EssentialsRoomBase, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction
{ {
private readonly EssentialsTechRoomConfig _config; public EssentialsTechRoomConfig PropertiesConfig { get; private set; }
private readonly Dictionary<string, TwoWayDisplayBase> _displays; private readonly Dictionary<string, TwoWayDisplayBase> _displays;
private readonly DevicePresetsModel _tunerPresets; private readonly DevicePresetsModel _tunerPresets;
@ -57,16 +57,16 @@ namespace PepperDash.Essentials
public EssentialsTechRoom(DeviceConfig config) : base(config) public EssentialsTechRoom(DeviceConfig config) : base(config)
{ {
_config = config.Properties.ToObject<EssentialsTechRoomConfig>(); PropertiesConfig = config.Properties.ToObject<EssentialsTechRoomConfig>();
_tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), _config.PresetsFileName); _tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), PropertiesConfig.PresetsFileName);
_tunerPresets.SetFileName(_config.PresetsFileName); _tunerPresets.SetFileName(PropertiesConfig.PresetsFileName);
_tunerPresets.PresetRecalled += TunerPresetsOnPresetRecalled; _tunerPresets.PresetRecalled += TunerPresetsOnPresetRecalled;
_tuners = GetDevices<IRSetTopBoxBase>(_config.Tuners); _tuners = GetDevices<IRSetTopBoxBase>(PropertiesConfig.Tuners);
_displays = GetDevices<TwoWayDisplayBase>(_config.Displays); _displays = GetDevices<TwoWayDisplayBase>(PropertiesConfig.Displays);
RoomPowerIsOnFeedback = new BoolFeedback(() => RoomPowerIsOn); RoomPowerIsOnFeedback = new BoolFeedback(() => RoomPowerIsOn);
@ -153,7 +153,7 @@ namespace PepperDash.Essentials
private void CreateOrUpdateScheduledEvents() private void CreateOrUpdateScheduledEvents()
{ {
var eventsConfig = _config.ScheduledEvents; var eventsConfig = PropertiesConfig.ScheduledEvents;
GetOrCreateScheduleGroup(); GetOrCreateScheduleGroup();
@ -207,21 +207,21 @@ namespace PepperDash.Essentials
{ {
//update config based on key of scheduleEvent //update config based on key of scheduleEvent
GetOrCreateScheduleGroup(); GetOrCreateScheduleGroup();
var existingEventIndex = _config.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key); var existingEventIndex = PropertiesConfig.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key);
if (existingEventIndex < 0) if (existingEventIndex < 0)
{ {
_config.ScheduledEvents.Add(scheduledEvent); PropertiesConfig.ScheduledEvents.Add(scheduledEvent);
} }
else else
{ {
_config.ScheduledEvents[existingEventIndex] = scheduledEvent; PropertiesConfig.ScheduledEvents[existingEventIndex] = scheduledEvent;
} }
//create or update event based on config //create or update event based on config
CreateOrUpdateSingleEvent(scheduledEvent); CreateOrUpdateSingleEvent(scheduledEvent);
//save config //save config
Config.Properties = JToken.FromObject(_config); Config.Properties = JToken.FromObject(PropertiesConfig);
CustomSetConfig(Config); CustomSetConfig(Config);
//Fire Event //Fire Event
@ -230,7 +230,7 @@ namespace PepperDash.Essentials
public List<ScheduledEventConfig> GetScheduledEvents() public List<ScheduledEventConfig> GetScheduledEvents()
{ {
return _config.ScheduledEvents ?? new List<ScheduledEventConfig>(); return PropertiesConfig.ScheduledEvents ?? new List<ScheduledEventConfig>();
} }
private void OnScheduledEventUpdate() private void OnScheduledEventUpdate()
@ -242,14 +242,14 @@ namespace PepperDash.Essentials
return; return;
} }
handler(this, new ScheduledEventEventArgs {ScheduledEvents = _config.ScheduledEvents}); handler(this, new ScheduledEventEventArgs {ScheduledEvents = PropertiesConfig.ScheduledEvents});
} }
public event EventHandler<ScheduledEventEventArgs> ScheduledEventsChanged; public event EventHandler<ScheduledEventEventArgs> ScheduledEventsChanged;
private void HandleScheduledEvent(ScheduledEvent schevent, ScheduledEventCommon.eCallbackReason type) private void HandleScheduledEvent(ScheduledEvent schevent, ScheduledEventCommon.eCallbackReason type)
{ {
var eventConfig = _config.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name); var eventConfig = PropertiesConfig.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name);
if (eventConfig == null) if (eventConfig == null)
{ {
@ -286,11 +286,11 @@ Params: {2}"
{ {
Debug.Console(2, this, "Room Powering On"); Debug.Console(2, this, "Room Powering On");
var dummySource = DeviceManager.GetDeviceForKey(_config.DummySourceKey) as IRoutingOutputs; var dummySource = DeviceManager.GetDeviceForKey(PropertiesConfig.DummySourceKey) as IRoutingOutputs;
if (dummySource == null) if (dummySource == null)
{ {
Debug.Console(1, this, "Unable to get source with key: {0}", _config.DummySourceKey); Debug.Console(1, this, "Unable to get source with key: {0}", PropertiesConfig.DummySourceKey);
return; return;
} }
@ -375,13 +375,13 @@ Params: {2}"
{ {
bridge.AddJoinMap(Key, joinMap); bridge.AddJoinMap(Key, joinMap);
} }
uint i;
if (_config.IsPrimary) if (PropertiesConfig.IsPrimary)
{ {
Debug.Console(1, this, "Linking Primary system Tuner Preset Mirroring"); Debug.Console(1, this, "Linking Primary system Tuner Preset Mirroring");
if (_config.MirroredTuners != null && _config.MirroredTuners.Count > 0) if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0)
{ {
foreach (var tuner in _config.MirroredTuners) foreach (var tuner in PropertiesConfig.MirroredTuners)
{ {
var f = CurrentPresetsFeedbacks[tuner.Value]; var f = CurrentPresetsFeedbacks[tuner.Value];
@ -423,9 +423,9 @@ Params: {2}"
{ {
Debug.Console(1, this, "Linking Secondary system Tuner Preset Mirroring"); Debug.Console(1, this, "Linking Secondary system Tuner Preset Mirroring");
if (_config.MirroredTuners != null && _config.MirroredTuners.Count > 0) if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0)
{ {
foreach (var tuner in _config.MirroredTuners) foreach (var tuner in PropertiesConfig.MirroredTuners)
{ {
var t = _tuners[tuner.Value]; var t = _tuners[tuner.Value];

View file

@ -12,6 +12,8 @@ namespace PepperDash.Essentials
{ {
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey); void RunRouteAction(string routeKey);
IHasScheduleAwareness ScheduleSource { get; } IHasScheduleAwareness ScheduleSource { get; }

View file

@ -16,6 +16,8 @@ namespace PepperDash.Essentials
{ {
public class EssentialsTouchpanelController : EssentialsDevice, IHasBasicTriListWithSmartObject public class EssentialsTouchpanelController : EssentialsDevice, IHasBasicTriListWithSmartObject
{ {
private CrestronTouchpanelPropertiesConfig _propertiesConfig;
public BasicTriListWithSmartObject Panel { get; private set; } public BasicTriListWithSmartObject Panel { get; private set; }
public PanelDriverBase PanelDriver { get; private set; } public PanelDriverBase PanelDriver { get; private set; }
@ -27,7 +29,14 @@ namespace PepperDash.Essentials
: base(key, name) : base(key, name)
{ {
Panel = tsw; Panel = tsw;
tsw.LoadSmartObjects(sgdPath);
if (!string.IsNullOrEmpty(sgdPath))
Panel.LoadSmartObjects(sgdPath);
else
Debug.Console(1, this, "No SGD file path defined");
tsw.SigChange += Panel_SigChange; tsw.SigChange += Panel_SigChange;
} }
@ -37,7 +46,7 @@ namespace PepperDash.Essentials
Panel = dge; Panel = dge;
if (!string.IsNullOrEmpty(sgdPath)) if (!string.IsNullOrEmpty(sgdPath))
dge.LoadSmartObjects(sgdPath); Panel.LoadSmartObjects(sgdPath);
else else
Debug.Console(1, this, "No SGD file path defined"); Debug.Console(1, this, "No SGD file path defined");
@ -50,6 +59,7 @@ namespace PepperDash.Essentials
public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id) public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
: base(key, name) : base(key, name)
{ {
_propertiesConfig = props;
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware..."); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware...");
type = type.ToLower(); type = type.ToLower();
@ -61,6 +71,8 @@ namespace PepperDash.Essentials
app.ParameterProjectName.Value = props.ProjectName; app.ParameterProjectName.Value = props.ProjectName;
Panel = app; Panel = app;
} }
else if (type == "xpanel")
Panel = new XpanelForSmartGraphics(id, Global.ControlSystem);
else if (type == "tsw550") else if (type == "tsw550")
Panel = new Tsw550(id, Global.ControlSystem); Panel = new Tsw550(id, Global.ControlSystem);
else if (type == "tsw552") else if (type == "tsw552")
@ -134,10 +146,194 @@ namespace PepperDash.Essentials
Panel.LoadSmartObjects(sgdName); Panel.LoadSmartObjects(sgdName);
Panel.SigChange += Panel_SigChange; 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) public void LoadAndShowDriver(PanelDriverBase driver)
{ {
if (PanelDriver != null)
{
var mainDriver = PanelDriver as EssentialsPanelMainInterfaceDriver;
if (mainDriver != null)
{
mainDriver.Dispose();
}
}
PanelDriver = driver; PanelDriver = driver;
driver.Show(); driver.Show();
} }
@ -148,7 +344,6 @@ namespace PepperDash.Essentials
PanelDriver.BackButtonPressed(); PanelDriver.BackButtonPressed();
} }
void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
{ {
// If the sig is transitioning on, mark it in case it was home button that transitioned it // If the sig is transitioning on, mark it in case it was home button that transitioned it
@ -213,7 +408,7 @@ namespace PepperDash.Essentials
{ {
public EssentialsTouchpanelControllerFactory() public EssentialsTouchpanelControllerFactory()
{ {
TypeNames = new List<string>() { "tsw550", "tsw750", "tsw1050", "tsw560", "tsw760", "tsw1060", "tsw570", "tsw770", "ts770", "tsw1070", "ts1070", "xpanel" }; TypeNames = new List<string>() { "crestronapp", "tsw550", "tsw750", "tsw1050", "tsw560", "tsw760", "tsw1060", "tsw570", "tsw770", "ts770", "tsw1070", "ts1070", "xpanel" };
} }
public override EssentialsDevice BuildDevice(DeviceConfig dc) public override EssentialsDevice BuildDevice(DeviceConfig dc)
@ -225,119 +420,6 @@ namespace PepperDash.Essentials
var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, dc.Type, props, comm.IpIdInt); 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; return panelController;
} }
} }

View file

@ -14,6 +14,8 @@ namespace PepperDash.Essentials
{ {
public SourceListItem SourceItem { get; private set; } public SourceListItem SourceItem { get; private set; }
private IHasCurrentSourceInfoChange _room;
public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner, public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner,
SourceListItem sourceItem, Action<bool> routeAction) SourceListItem sourceItem, Action<bool> routeAction)
: base(index, owner) : base(index, owner)
@ -25,6 +27,7 @@ namespace PepperDash.Essentials
public void RegisterForSourceChange(IHasCurrentSourceInfoChange room) public void RegisterForSourceChange(IHasCurrentSourceInfoChange room)
{ {
_room = room;
room.CurrentSourceChange -= room_CurrentSourceInfoChange; room.CurrentSourceChange -= room_CurrentSourceInfoChange;
room.CurrentSourceChange += room_CurrentSourceInfoChange; room.CurrentSourceChange += room_CurrentSourceInfoChange;
} }
@ -44,6 +47,9 @@ namespace PepperDash.Essentials
{ {
Owner.BoolInputSig(Index, 1).UserObject = null; Owner.BoolInputSig(Index, 1).UserObject = null;
Owner.StringInputSig(Index, 1).StringValue = ""; Owner.StringInputSig(Index, 1).StringValue = "";
if(_room != null)
_room.CurrentSourceChange -= room_CurrentSourceInfoChange;
} }
/// <summary> /// <summary>

View file

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

View file

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

View file

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

View file

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

View file

@ -632,7 +632,6 @@ namespace PepperDash.Essentials.UIDrivers.VC
VCControlsInterlock.StatusChanged += new EventHandler<StatusChangedEventArgs>(VCControlsInterlock_StatusChanged); VCControlsInterlock.StatusChanged += new EventHandler<StatusChangedEventArgs>(VCControlsInterlock_StatusChanged);
var codecOffCameras = Codec as IHasCameraOff; var codecOffCameras = Codec as IHasCameraOff;
var supportsCameraOffMode = Codec.SupportsCameraOff; var supportsCameraOffMode = Codec.SupportsCameraOff;
@ -643,6 +642,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (codecAutoCameras != null && supportsAutoCameraMode) if (codecAutoCameras != null && supportsAutoCameraMode)
{ {
CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn()); CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn());
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true; TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true;
codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]); codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]);
@ -672,6 +672,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
} }
}; };
} }
// Manual button always visible // Manual button always visible
@ -683,6 +684,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (codecOffCameras != null && supportsCameraOffMode) if (codecOffCameras != null && supportsCameraOffMode)
{ {
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true; TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true;
codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]); codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]);
CameraModeList.SetItemButtonAction(3, (b) => codecOffCameras.CameraOff()); CameraModeList.SetItemButtonAction(3, (b) => codecOffCameras.CameraOff());
@ -710,6 +712,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
} }
}; };
} }
} }

View file

@ -54,6 +54,10 @@ Utilization of Essentials Framework falls into the following categories:
For detailed documentation, see the [Wiki](https://github.com/PepperDash/EssentialsFramework/wiki). For detailed documentation, see the [Wiki](https://github.com/PepperDash/EssentialsFramework/wiki).
## Support
* Check out our [Discord Server](https://discord.gg/rWyeRH3K)
## How-To (Getting Started) ## How-To (Getting Started)
See [Getting Started](https://github.com/PepperDash/Essentials/wiki/Get-started#how-to-get-started) See [Getting Started](https://github.com/PepperDash/Essentials/wiki/Get-started#how-to-get-started)

View file

@ -42,3 +42,6 @@ devjson:2 {"deviceKey":"display01Comm-com", "methodName":"SendText", "params": [
devjson:10 {"deviceKey":"dmLink-ssh", "methodName":"Connect", "params": []} devjson:10 {"deviceKey":"dmLink-ssh", "methodName":"Connect", "params": []}
devjson:2 {"deviceKey":"roomCombiner", "methodName":"SetRoomCombinationScenario", "params": ["combined"]}
devjson:2 {"deviceKey":"roomCombiner", "methodName":"SetRoomCombinationScenario", "params": ["divided"]}

View file

@ -84,6 +84,10 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete OutputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1601, JoinSpan = 32 }, public JoinDataComplete OutputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1601, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("NoRouteName")]
public JoinDataComplete NoRouteName = new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 },
new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("InputNames")] [JoinName("InputNames")]
public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
@ -96,7 +100,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinDataComplete(new JoinData {JoinNumber = 501, JoinSpan = 200}, new JoinDataComplete(new JoinData {JoinNumber = 501, JoinSpan = 200},
new JoinMetadata new JoinMetadata
{ {
Description = "Video Input Name", Description = "DM Chassis Video Input Names",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
@ -106,7 +110,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 200 }, new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 200 },
new JoinMetadata new JoinMetadata
{ {
Description = "Video Input Name", Description = "DM Chassis Audio Input Names",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
@ -115,7 +119,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 200 }, new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 200 },
new JoinMetadata new JoinMetadata
{ {
Description = "Video Input Name", Description = "DM Chassis Video Output Names",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
@ -124,7 +128,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 200 }, new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 200 },
new JoinMetadata new JoinMetadata
{ {
Description = "Video Input Name", Description = "DM Chassis Audio Output Names",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });

View file

@ -28,6 +28,10 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete EdidSerialNumber = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, public JoinDataComplete EdidSerialNumber = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 },
new JoinMetadata { Description = "DM RMC EDID Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM RMC EDID Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("Name")]
public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 },
new JoinMetadata { Description = "DM RMC Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("AudioVideoSource")] [JoinName("AudioVideoSource")]
public JoinDataComplete AudioVideoSource = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete AudioVideoSource = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "DM RMC Audio Video Source Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "DM RMC Audio Video Source Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });

View file

@ -32,6 +32,10 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete CurrentInputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete CurrentInputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "DM TX Current Input Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM TX Current Input Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("Name")]
public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata { Description = "DM TX Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("VideoInput")] [JoinName("VideoInput")]
public JoinDataComplete VideoInput = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete VideoInput = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "DM TX Video Input Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "DM TX Video Input Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
@ -42,7 +46,7 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("HdcpSupportCapability")] [JoinName("HdcpSupportCapability")]
public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata { Description = "DM TX HDCP Support Capability", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "DM TX HDCP Support Capability", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog });
[JoinName("Port1HdcpState")] [JoinName("Port1HdcpState")]
public JoinDataComplete Port1HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, public JoinDataComplete Port1HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 },

View file

@ -7,7 +7,15 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("MasterVolumeLevel")] [JoinName("MasterVolumeLevel")]
public JoinDataComplete MasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete MasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "Master Volume Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "Master Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MasterVolumeLevelScaled")]
public JoinDataComplete MasterVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata { Description = "Master Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MixerPresetRecall")]
public JoinDataComplete MixerPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata { Description = "Mixer Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MasterVolumeMuteOn")] [JoinName("MasterVolumeMuteOn")]
public JoinDataComplete MasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete MasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
@ -23,11 +31,19 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("MasterVolumeDown")] [JoinName("MasterVolumeDown")]
public JoinDataComplete MasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, public JoinDataComplete MasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 },
new JoinMetadata { Description = "Master Volume Mute Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Master Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MasterVolumeLevelScaledSend")]
public JoinDataComplete MasterVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 },
new JoinMetadata { Description = "Master Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("SourceVolumeLevel")] [JoinName("SourceVolumeLevel")]
public JoinDataComplete SourceVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, public JoinDataComplete SourceVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata { Description = "Source Volume Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "Source Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("SourceVolumeLevelScaled")]
public JoinDataComplete SourceVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata { Description = "Source Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("SourceVolumeMuteOn")] [JoinName("SourceVolumeMuteOn")]
public JoinDataComplete SourceVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, public JoinDataComplete SourceVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 },
@ -43,11 +59,19 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("SourceVolumeDown")] [JoinName("SourceVolumeDown")]
public JoinDataComplete SourceVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, public JoinDataComplete SourceVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 },
new JoinMetadata { Description = "Source Volume Mute Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Source Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("SourceVolumeLevelScaledSend")]
public JoinDataComplete SourceVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 },
new JoinMetadata { Description = "Source Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("Codec1VolumeLevel")] [JoinName("Codec1VolumeLevel")]
public JoinDataComplete Codec1VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, public JoinDataComplete Codec1VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 },
new JoinMetadata { Description = "Codec1 Volume Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "Codec1 Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("Codec1VolumeLevelScaled")]
public JoinDataComplete Codec1VolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 },
new JoinMetadata { Description = "Codec1 Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("Codec1VolumeMuteOn")] [JoinName("Codec1VolumeMuteOn")]
public JoinDataComplete Codec1VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, public JoinDataComplete Codec1VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 },
@ -63,11 +87,19 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("Codec1VolumeDown")] [JoinName("Codec1VolumeDown")]
public JoinDataComplete Codec1VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, public JoinDataComplete Codec1VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 },
new JoinMetadata { Description = "Codec1 Volume Mute Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Codec1 Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("Codec1VolumeLevelScaledSend")]
public JoinDataComplete Codec1VolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 },
new JoinMetadata { Description = "Codec1 Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("Codec2VolumeLevel")] [JoinName("Codec2VolumeLevel")]
public JoinDataComplete Codec2VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, public JoinDataComplete Codec2VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 },
new JoinMetadata { Description = "Codec2 Volume Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "Codec2 Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("Codec2VolumeLevelScaled")]
public JoinDataComplete Codec2VolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 },
new JoinMetadata { Description = "Codec2 Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("Codec2VolumeMuteOn")] [JoinName("Codec2VolumeMuteOn")]
public JoinDataComplete Codec2VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, public JoinDataComplete Codec2VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 },
@ -83,8 +115,39 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("Codec2VolumeDown")] [JoinName("Codec2VolumeDown")]
public JoinDataComplete Codec2VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, public JoinDataComplete Codec2VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 },
new JoinMetadata { Description = "Codec2 Volume Mute Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Codec2 Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("Codec2VolumeLevelScaledSend")]
public JoinDataComplete Codec2VolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 },
new JoinMetadata { Description = "Codec2 Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeLevel")]
public JoinDataComplete MicsMasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MicsMasterVolumeLevelScaled")]
public JoinDataComplete MicsMasterVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MicsMasterVolumeMuteOn")]
public JoinDataComplete MicsMasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeMuteOff")]
public JoinDataComplete MicsMasterVolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeUp")]
public JoinDataComplete MicsMasterVolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeDown")]
public JoinDataComplete MicsMasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 44, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeLevelScaledSend")]
public JoinDataComplete MicsMasterVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 45, JoinSpan = 1 },
new JoinMetadata { Description = "Mics Master Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
/// <summary> /// <summary>
/// Constructor to use when instantiating this Join Map without inheriting from it /// Constructor to use when instantiating this Join Map without inheriting from it

View file

@ -0,0 +1,50 @@
using System;
namespace PepperDash.Essentials.Core.Bridges
{
public class DmpsMicrophoneControllerJoinMap : JoinMapBaseAdvanced
{
[JoinName("MicGain")]
public JoinDataComplete MicGain = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Gain dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MicGainScaled")]
public JoinDataComplete MicGainScaled = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Gain 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MicMuteOn")]
public JoinDataComplete MicMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicMuteOff")]
public JoinDataComplete MicMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicGainScaledSend")]
public JoinDataComplete MicGainScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Gain Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicName")]
public JoinDataComplete MicName = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Name Get", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
/// <summary>
/// Constructor to use when instantiating this Join Map without inheriting from it
/// </summary>
/// <param name="joinStart">Join this join map will start at</param>
public DmpsMicrophoneControllerJoinMap(uint joinStart)
: this(joinStart, typeof(DmpsMicrophoneControllerJoinMap))
{
}
/// <summary>
/// Constructor to use when extending this Join map
/// </summary>
/// <param name="joinStart">Join this join map will start at</param>
/// <param name="type">Type of the child join map</param>
protected DmpsMicrophoneControllerJoinMap(uint joinStart, Type type)
: base(joinStart, type)
{
}
}
}

View file

@ -4,6 +4,10 @@ namespace PepperDash.Essentials.Core.Bridges
{ {
public class DmpsRoutingControllerJoinMap : JoinMapBaseAdvanced public class DmpsRoutingControllerJoinMap : JoinMapBaseAdvanced
{ {
[JoinName("EnableRouting")]
public JoinDataComplete EnableRouting = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS Enable Audio and Video Routing", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("SystemPowerOn")] [JoinName("SystemPowerOn")]
public JoinDataComplete SystemPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, public JoinDataComplete SystemPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS System Power On Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "DMPS System Power On Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
@ -12,6 +16,14 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete SystemPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, public JoinDataComplete SystemPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS System Power Off Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "DMPS System Power Off Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("FrontPanelLockOn")]
public JoinDataComplete FrontPanelLockOn = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS Front Panel Lock On Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("FrontPanelLockOff")]
public JoinDataComplete FrontPanelLockOff = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS Front Panel Lock Off Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("VideoSyncStatus")] [JoinName("VideoSyncStatus")]
public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 },
new JoinMetadata { Description = "DM Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "DM Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital });
@ -40,6 +52,44 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("InputVideoNames")]
public JoinDataComplete InputVideoNames =
new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 },
new JoinMetadata
{
Description = "Video Input Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("InputAudioNames")]
public JoinDataComplete InputAudioNames =
new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 },
new JoinMetadata
{
Description = "Audio Input Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("OutputVideoNames")]
public JoinDataComplete OutputVideoNames =
new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 32 },
new JoinMetadata
{
Description = "Video Output Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("OutputAudioNames")]
public JoinDataComplete OutputAudioNames =
new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 32 },
new JoinMetadata
{
Description = "Audio Output Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("OutputCurrentVideoInputNames")] [JoinName("OutputCurrentVideoInputNames")]
public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 32 }, public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });

View file

@ -45,7 +45,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinMetadata { Description = "Processor Last Boot", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "Processor Last Boot", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("ProgramOffsetJoin")] [JoinName("ProgramOffsetJoin")]
public JoinDataComplete ProgramOffsetJoin = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, public JoinDataComplete ProgramOffsetJoin = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 5 },
new JoinMetadata { Description = "All Program Data is offset between slots by 5 - First Joins Start at 11", JoinCapabilities = eJoinCapabilities.None, JoinType = eJoinType.None }); new JoinMetadata { Description = "All Program Data is offset between slots by 5 - First Joins Start at 11", JoinCapabilities = eJoinCapabilities.None, JoinType = eJoinType.None });
[JoinName("ProgramStart")] [JoinName("ProgramStart")]

View file

@ -1145,7 +1145,22 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
#region Analog #region Analog
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
[JoinName("MeetingsToDisplay")]
public JoinDataComplete MeetingsToDisplay = new JoinDataComplete(
new JoinData
{
JoinNumber = 40,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Set/FB the number of meetings to display via the bridge xsig; default: 3 meetings.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("SelectCall")] [JoinName("SelectCall")]
public JoinDataComplete SelectCall = new JoinDataComplete( public JoinDataComplete SelectCall = new JoinDataComplete(

View file

@ -0,0 +1,77 @@
using System.Collections.Generic;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.GeneralIO;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Wrapper class for CEN-IO-RY-104 relay module
/// </summary>
[Description("Wrapper class for the CEN-IO-RY-104 relay module")]
public class CenIoRy104Controller : EssentialsDevice, IRelayPorts
{
private readonly CenIoRy104 _ry104;
/// <summary>
/// Constructor
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="ry104"></param>
public CenIoRy104Controller(string key, string name, CenIoRy104 ry104)
: base(key, name)
{
_ry104 = ry104;
}
/// <summary>
/// Relay port collection
/// </summary>
public CrestronCollection<Relay> RelayPorts
{
get { return _ry104.RelayPorts; }
}
/// <summary>
/// Number of relay ports property
/// </summary>
public int NumberOfRelayPorts
{
get { return _ry104.NumberOfRelayPorts; }
}
}
/// <summary>
/// CEN-IO-RY Controller factory
/// </summary>
public class CenIoRy104ControllerFactory : EssentialsDeviceFactory<CenIoRy104Controller>
{
/// <summary>
/// Constructor
/// </summary>
public CenIoRy104ControllerFactory()
{
TypeNames = new List<string>() { "ceniory104" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create a new CEN-IO-RY-104 Device");
var controlPropertiesConfig = CommFactory.GetControlPropertiesConfig(dc);
if (controlPropertiesConfig == null)
{
Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device");
return null;
}
var ipid = controlPropertiesConfig.IpIdInt;
if (ipid != 0) return new CenIoRy104Controller(dc.Key, dc.Name, new CenIoRy104(ipid, Global.ControlSystem));
Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device using IP-ID-{0}", ipid);
return null;
}
}
}

View file

@ -44,6 +44,12 @@ namespace PepperDash.Essentials.Core.CrestronIO
{ {
RelayOutput = postActivationFunc(config); RelayOutput = postActivationFunc(config);
if (RelayOutput == null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Unable to get parent relay device for device key {0} and port {1}", config.PortDeviceKey, config.PortNumber);
return;
}
RelayOutput.Register(); RelayOutput.Register();
RelayOutput.StateChange += RelayOutput_StateChange; RelayOutput.StateChange += RelayOutput_StateChange;
@ -61,33 +67,36 @@ namespace PepperDash.Essentials.Core.CrestronIO
{ {
if (!Global.ControlSystem.SupportsRelay) if (!Global.ControlSystem.SupportsRelay)
{ {
Debug.Console(0, "GetRelayDevice: Processor does not support relays"); Debug.Console(0, "Processor does not support relays");
return null; return null;
} }
relayDevice = Global.ControlSystem; relayDevice = Global.ControlSystem;
return relayDevice.RelayPorts[dc.PortNumber];
} }
else
var essentialsDevice = DeviceManager.GetDeviceForKey(dc.PortDeviceKey);
if (essentialsDevice == null)
{ {
var relayDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IRelayPorts; Debug.Console(0, "Device {0} was not found in Device Manager. Check configuration or for errors with device.", dc.PortDeviceKey);
if (relayDev == null)
{
Debug.Console(0, "GetRelayDevice: Device {0} is not a valid device", dc.PortDeviceKey);
return null;
}
relayDevice = relayDev;
}
if (relayDevice == null)
{
Debug.Console(0, "GetRelayDevice: Device '0' is not a valid IRelayPorts Device", dc.PortDeviceKey);
return null; return null;
} }
if (dc.PortNumber > relayDevice.NumberOfRelayPorts) relayDevice = essentialsDevice as IRelayPorts;
{
Debug.Console(0, "GetRelayDevice: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
}
return relayDevice.RelayPorts[dc.PortNumber]; if (relayDevice == null)
{
Debug.Console(0, "Device {0} is not a valid relay parent. Please check configuration.", dc.PortDeviceKey);
return null;
}
if (dc.PortNumber <= relayDevice.NumberOfRelayPorts)
{
return relayDevice.RelayPorts[dc.PortNumber];
}
Debug.Console(0, "Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
return null;
} }
#endregion #endregion
@ -200,58 +209,6 @@ namespace PepperDash.Essentials.Core.CrestronIO
var portDevice = new GenericRelayDevice(dc.Key, dc.Name, GetRelay, props); var portDevice = new GenericRelayDevice(dc.Key, dc.Name, GetRelay, props);
return portDevice; return portDevice;
/*
if (props.PortDeviceKey == "processor")
portDevice = Global.ControlSystem as IRelayPorts;
else
portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts;
if (portDevice == null)
Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key);
else
{
var cs = (portDevice as CrestronControlSystem);
if (cs != null)
{
// The relay is on a control system processor
if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts)
{
Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays");
return null;
}
}
else
{
// The relay is on another device type
if (props.PortNumber > portDevice.NumberOfRelayPorts)
{
Debug.Console(0, "Port Device: {0} does not have enough relays");
return null;
}
}
Relay relay = portDevice.RelayPorts[props.PortNumber];
if (!relay.Registered)
{
if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success)
return new GenericRelayDevice(key, relay);
else
Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey);
}
else
{
return new GenericRelayDevice(key, relay);
}
// Future: Check if portDevice is 3-series card or other non control system that supports versiports
}
*/
} }
} }

View file

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

View file

@ -1,83 +1,83 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json; using Newtonsoft.Json;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Core.Lighting namespace PepperDash.Essentials.Core.Lighting
{ {
public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes
{ {
#region ILightingScenes Members #region ILightingScenes Members
public event EventHandler<LightingSceneChangeEventArgs> LightingSceneChange; public event EventHandler<LightingSceneChangeEventArgs> LightingSceneChange;
public List<LightingScene> LightingScenes { get; protected set; } public List<LightingScene> LightingScenes { get; protected set; }
public LightingScene CurrentLightingScene { get; protected set; } public LightingScene CurrentLightingScene { get; protected set; }
public IntFeedback CurrentLightingSceneFeedback { get; protected set; } public IntFeedback CurrentLightingSceneFeedback { get; protected set; }
#endregion #endregion
protected LightingBase(string key, string name) protected LightingBase(string key, string name)
: base(key, name) : base(key, name)
{
LightingScenes = new List<LightingScene>();
CurrentLightingScene = new LightingScene();
//CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); });
}
public abstract void SelectScene(LightingScene scene);
public void SimulateSceneSelect(string sceneName)
{
Debug.Console(1, this, "Simulating selection of scene '{0}'", sceneName);
var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName));
if (scene != null)
{
CurrentLightingScene = scene;
OnLightingSceneChange();
}
}
/// <summary>
/// Sets the IsActive property on each scene and fires the LightingSceneChange event
/// </summary>
protected void OnLightingSceneChange()
{
foreach (var scene in LightingScenes)
{
if (scene == CurrentLightingScene)
scene.IsActive = true;
else
scene.IsActive = false;
}
var handler = LightingSceneChange;
if (handler != null)
{
handler(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
{ {
var joinMap = new GenericLightingJoinMap(joinStart); LightingScenes = new List<LightingScene>();
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); CurrentLightingScene = new LightingScene();
//CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); });
if (!string.IsNullOrEmpty(joinMapSerialized)) }
public abstract void SelectScene(LightingScene scene);
public void SimulateSceneSelect(string sceneName)
{
Debug.Console(1, this, "Simulating selection of scene '{0}'", sceneName);
var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName));
if (scene != null)
{
CurrentLightingScene = scene;
OnLightingSceneChange();
}
}
/// <summary>
/// Sets the IsActive property on each scene and fires the LightingSceneChange event
/// </summary>
protected void OnLightingSceneChange()
{
foreach (var scene in LightingScenes)
{
if (scene == CurrentLightingScene)
scene.IsActive = true;
else
scene.IsActive = false;
}
var handler = LightingSceneChange;
if (handler != null)
{
handler(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GenericLightingJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized); joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
if (bridge != null) if (bridge != null)
@ -87,52 +87,57 @@ namespace PepperDash.Essentials.Core.Lighting
else else
{ {
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
} }
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString()); Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
// GenericLighitng Actions & FeedBack // GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u])); trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
var sceneIndex = 0; var sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes) foreach (var scene in lightingDevice.LightingScenes)
{ {
trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[sceneIndex])); trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[sceneIndex]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)]); scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)]);
trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)].StringValue = scene.Name; trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + sceneIndex)].BoolValue = true; trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + sceneIndex)].BoolValue = true;
sceneIndex++; sceneIndex++;
} }
return joinMap; return joinMap;
} }
} }
public class LightingScene public class LightingScene
{ {
public string Name { get; set; } [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string ID { get; set; } public string Name { get; set; }
bool _IsActive; [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public bool IsActive public string ID { get; set; }
{ bool _IsActive;
get [JsonProperty("isActive", NullValueHandling = NullValueHandling.Ignore)]
{ public bool IsActive
return _IsActive; {
} get
set {
{ return _IsActive;
_IsActive = value; }
IsActiveFeedback.FireUpdate(); set
} {
} _IsActive = value;
public BoolFeedback IsActiveFeedback { get; set; } IsActiveFeedback.FireUpdate();
}
public LightingScene() }
{
IsActiveFeedback = new BoolFeedback(new Func<bool>(() => IsActive)); [JsonIgnore]
} public BoolFeedback IsActiveFeedback { get; set; }
}
public LightingScene()
{
IsActiveFeedback = new BoolFeedback(new Func<bool>(() => IsActive));
}
}
} }

View file

@ -301,7 +301,7 @@ namespace PepperDash.Essentials.Core.Monitoring
p.Value.AggregatedProgramInfoFeedback.LinkInputSig( p.Value.AggregatedProgramInfoFeedback.LinkInputSig(
trilist.StringInput[programSlotJoinStart + joinMap.AggregatedProgramInfo.JoinNumber]); trilist.StringInput[programSlotJoinStart + joinMap.AggregatedProgramInfo.JoinNumber]);
programSlotJoinStart = programSlotJoinStart + joinMap.ProgramOffsetJoin.JoinNumber; programSlotJoinStart = programSlotJoinStart + joinMap.ProgramOffsetJoin.JoinSpan;
} }
} }

View file

@ -131,6 +131,7 @@
<Compile Include="Bridges\JoinMaps\DmBladeChassisControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmBladeChassisControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmChassisControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmChassisControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmpsAudioOutputControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmpsAudioOutputControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmpsMicrophoneControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmpsRoutingControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmpsRoutingControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmRmcControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmRmcControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmTxControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmTxControllerJoinMap.cs" />
@ -182,6 +183,7 @@
<Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.cs" /> <Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.cs" />
<Compile Include="Crestron IO\Inputs\IDigitalInput.cs" /> <Compile Include="Crestron IO\Inputs\IDigitalInput.cs" />
<Compile Include="Crestron IO\IOPortConfig.cs" /> <Compile Include="Crestron IO\IOPortConfig.cs" />
<Compile Include="Crestron IO\Relay\CenIoRy104Controller.cs" />
<Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" /> <Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" />
<Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" /> <Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" />
<Compile Include="Crestron IO\StatusSign\StatusSignController.cs" /> <Compile Include="Crestron IO\StatusSign\StatusSignController.cs" />

View file

@ -139,7 +139,8 @@ namespace PepperDash.Essentials.Core.Queues
_queue = new CrestronQueue<IQueueMessage>(cap); _queue = new CrestronQueue<IQueueMessage>(cap);
_worker = new Thread(ProcessQueue, null, Thread.eThreadStartOptions.Running) _worker = new Thread(ProcessQueue, null, Thread.eThreadStartOptions.Running)
{ {
Priority = priority Priority = priority,
Name = _key
}; };
SetDelayValues(pacing); SetDelayValues(pacing);

View file

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

View file

@ -30,7 +30,7 @@ namespace PepperDash.Essentials.Core
/// <summary> /// <summary>
/// The list of rooms keys that can be combined /// The list of rooms keys that can be combined
/// </summary> /// </summary>
[JsonProperty("roomMap")] [JsonProperty("roomKeys")]
public List<string> RoomKeys {get; set;} public List<string> RoomKeys {get; set;}
/// <summary> /// <summary>
@ -87,6 +87,9 @@ namespace PepperDash.Essentials.Core
[JsonProperty("partitionStates")] [JsonProperty("partitionStates")]
public List<PartitionState> PartitionStates { get; set; } 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")] [JsonProperty("uiMap")]
public Dictionary<string, string> UiMap { get; set; } public Dictionary<string, string> UiMap { get; set; }

View file

@ -78,6 +78,11 @@ namespace PepperDash.Essentials.Core
/// </summary> /// </summary>
void Activate(); void Activate();
/// <summary>
/// Deactivates this room combination scenario
/// </summary>
void Deactivate();
/// <summary> /// <summary>
/// The state of the partitions that would activate this scenario /// The state of the partitions that would activate this scenario
/// </summary> /// </summary>

View file

@ -4,6 +4,8 @@ using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using PepperDash.Core;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
@ -27,9 +29,9 @@ namespace PepperDash.Essentials.Core
public BoolFeedback IsActiveFeedback { get; private set; } public BoolFeedback IsActiveFeedback { get; private set; }
List<DeviceActionWrapper> activationActions; private List<DeviceActionWrapper> activationActions;
List<DeviceActionWrapper> deactivationActions; private List<DeviceActionWrapper> deactivationActions;
public RoomCombinationScenario(RoomCombinationScenarioConfig config) public RoomCombinationScenario(RoomCombinationScenarioConfig config)
{ {
@ -52,6 +54,8 @@ namespace PepperDash.Essentials.Core
public void Activate() public void Activate()
{ {
Debug.Console(1, "Activating Scenario: '{0}' with {1} action(s) defined", Name, activationActions.Count);
if (activationActions != null) if (activationActions != null)
{ {
foreach (var action in activationActions) foreach (var action in activationActions)
@ -66,6 +70,8 @@ namespace PepperDash.Essentials.Core
public void Deactivate() public void Deactivate()
{ {
Debug.Console(1, "Deactivating Scenario: '{0}' with {1} action(s) defined", Name, deactivationActions.Count);
if (deactivationActions != null) if (deactivationActions != null)
{ {
foreach (var action in deactivationActions) foreach (var action in deactivationActions)

View file

@ -11,6 +11,8 @@ using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices; using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
@ -18,6 +20,8 @@ namespace PepperDash.Essentials.Core
/// </summary> /// </summary>
public abstract class EssentialsRoomBase : ReconfigurableDevice, IEssentialsRoom public abstract class EssentialsRoomBase : ReconfigurableDevice, IEssentialsRoom
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@ -35,6 +39,16 @@ namespace PepperDash.Essentials.Core
public bool OccupancyStatusProviderIsRemote { get; private set; } public bool OccupancyStatusProviderIsRemote { get; private set; }
public List<EssentialsDevice> EnvironmentalControlDevices { get; protected set; }
public bool HasEnvironmentalControlDevices
{
get
{
return EnvironmentalControlDevices != null && EnvironmentalControlDevices.Count > 0;
}
}
protected abstract Func<bool> IsWarmingFeedbackFunc { get; } protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
protected abstract Func<bool> IsCoolingFeedbackFunc { get; } protected abstract Func<bool> IsCoolingFeedbackFunc { get; }
@ -119,6 +133,8 @@ namespace PepperDash.Essentials.Core
public EssentialsRoomBase(DeviceConfig config) public EssentialsRoomBase(DeviceConfig config)
: base(config) : base(config)
{ {
EnvironmentalControlDevices = new List<EssentialsDevice>();
// Setup the ShutdownPromptTimer // Setup the ShutdownPromptTimer
ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer"); ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) => ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>

View file

@ -15,7 +15,7 @@ namespace PepperDash.Essentials.Core
/// <summary> /// <summary>
/// Describes the basic functionality of an EssentialsRoom /// Describes the basic functionality of an EssentialsRoom
/// </summary> /// </summary>
public interface IEssentialsRoom : IKeyName, IReconfigurableDevice, IRunDefaultPresentRoute public interface IEssentialsRoom : IKeyName, IReconfigurableDevice, IRunDefaultPresentRoute, IEnvironmentalControls
{ {
BoolFeedback OnFeedback { get; } BoolFeedback OnFeedback { get; }

View file

@ -4,6 +4,8 @@ using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
@ -66,6 +68,14 @@ namespace PepperDash.Essentials.Core
bool RunDefaultCallRoute(); bool RunDefaultCallRoute();
} }
/// <summary>
/// Describes environmental controls available on a room such as lighting, shades, temperature, etc.
/// </summary>
public interface IEnvironmentalControls
{
List<EssentialsDevice> EnvironmentalControlDevices { get; }
bool HasEnvironmentalControlDevices { get; }
}
} }

View file

@ -31,6 +31,7 @@ namespace PepperDash.Essentials.Core.Shades
public interface IShadesOpenCloseStop : IShadesOpenClose public interface IShadesOpenCloseStop : IShadesOpenClose
{ {
void StopOrPreset(); void StopOrPreset();
string StopOrPresetButtonLabel { get; }
} }
/// <summary> /// <summary>

View file

@ -206,6 +206,27 @@ namespace PepperDash.Essentials.Core
return ClearSigAction(tl.StringOutput[sigNum]) as StringOutputSig; 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> /// <summary>
/// Helper method to set the value of a bool Sig on TriList /// Helper method to set the value of a bool Sig on TriList
/// </summary> /// </summary>

View file

@ -483,7 +483,7 @@ namespace PepperDash.Essentials.DM
Debug.Console(2, this, "Adding output port '{0}'", portKey); Debug.Console(2, this, "Adding output port '{0}'", portKey);
OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this) OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this)
{ {
FeedbackMatchObject = Chassis.Outputs[(uint)selector] FeedbackMatchObject = selector
}); });
}*/ }*/

View file

@ -1901,6 +1901,8 @@ namespace PepperDash.Essentials.DM
EnableAudioBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAudioBreakaway.JoinNumber]); EnableAudioBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAudioBreakaway.JoinNumber]);
EnableUsbBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsbBreakaway.JoinNumber]); EnableUsbBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsbBreakaway.JoinNumber]);
trilist.SetString(joinMap.NoRouteName.JoinNumber, NoRouteText);
trilist.OnlineStatusChange += (o, a) => trilist.OnlineStatusChange += (o, a) =>
{ {
if (!a.DeviceOnLine) if (!a.DeviceOnLine)
@ -1912,6 +1914,8 @@ namespace PepperDash.Essentials.DM
EnableUsbBreakawayFeedback.FireUpdate(); EnableUsbBreakawayFeedback.FireUpdate();
SystemIdBusyFeedback.FireUpdate(); SystemIdBusyFeedback.FireUpdate();
SystemIdFeebdack.FireUpdate(); SystemIdFeebdack.FireUpdate();
trilist.SetString(joinMap.NoRouteName.JoinNumber, NoRouteText);
}; };
} }

View file

@ -25,10 +25,10 @@ namespace PepperDash.Essentials.DM
public DmpsAudioOutput MasterVolumeLevel { get; private set; } public DmpsAudioOutput MasterVolumeLevel { get; private set; }
public DmpsAudioOutput SourceVolumeLevel { get; private set; } public DmpsAudioOutput SourceVolumeLevel { get; private set; }
public DmpsAudioOutput MicsMasterVolumeLevel { get; private set; }
public DmpsAudioOutput Codec1VolumeLevel { get; private set; } public DmpsAudioOutput Codec1VolumeLevel { get; private set; }
public DmpsAudioOutput Codec2VolumeLevel { get; private set; } public DmpsAudioOutput Codec2VolumeLevel { get; private set; }
public DmpsAudioOutputController(string key, string name, Card.Dmps3OutputBase card) public DmpsAudioOutputController(string key, string name, Card.Dmps3OutputBase card)
: base(key, name) : base(key, name)
{ {
@ -36,88 +36,143 @@ namespace PepperDash.Essentials.DM
OutputCard.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); OutputCard.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange);
MasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Master);
SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
if (card is Card.Dmps3ProgramOutput) if (card is Card.Dmps3ProgramOutput)
{ {
//(card as Card.Dmps3ProgramOutput).OutputMixer.MicLevel MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3ProgramOutput).OutputMixer);
//TODO: Hook up mic levels and mutes SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster);
Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1);
Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2);
} }
else if (card is Card.Dmps3Aux1Output) else if (card is Card.Dmps3Aux1Output)
{ {
MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3Aux1Output).OutputMixer);
SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster);
Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2);
} }
else if (card is Card.Dmps3Aux2Output) else if (card is Card.Dmps3Aux2Output)
{ {
MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3Aux2Output).OutputMixer);
SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster);
Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1);
} }
else //Digital Outputs
{
MasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Master);
SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster);
}
} }
void BaseDevice_DMOutputChange(Switch device, DMOutputEventArgs args) void BaseDevice_DMOutputChange(Switch device, DMOutputEventArgs args)
{ {
Debug.Console(2, this, "Dmps Audio Controller Event Output: {0} EventId: {1}", args.Number, args.EventId.ToString());
switch (args.EventId) switch (args.EventId)
{ {
case DMOutputEventIds.OutputVuFeedBackEventId:
{
//Frequently called event that isn't needed
return;
}
case DMOutputEventIds.MasterVolumeFeedBackEventId: case DMOutputEventIds.MasterVolumeFeedBackEventId:
{ {
MasterVolumeLevel.VolumeLevelFeedback.FireUpdate(); MasterVolumeLevel.VolumeLevelFeedback.FireUpdate();
break; MasterVolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
} break;
}
case DMOutputEventIds.MasterMuteOnFeedBackEventId: case DMOutputEventIds.MasterMuteOnFeedBackEventId:
{ {
MasterVolumeLevel.MuteFeedback.FireUpdate(); MasterVolumeLevel.MuteFeedback.FireUpdate();
break; break;
} }
case DMOutputEventIds.SourceLevelFeedBackEventId: case DMOutputEventIds.SourceLevelFeedBackEventId:
{ {
SourceVolumeLevel.VolumeLevelFeedback.FireUpdate(); SourceVolumeLevel.VolumeLevelFeedback.FireUpdate();
break; SourceVolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
} break;
}
case DMOutputEventIds.SourceMuteOnFeedBackEventId:
{
SourceVolumeLevel.MuteFeedback.FireUpdate();
break;
}
case DMOutputEventIds.MicMasterLevelFeedBackEventId:
{
MicsMasterVolumeLevel.VolumeLevelFeedback.FireUpdate();
MicsMasterVolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
break;
}
case DMOutputEventIds.MicMasterMuteOnFeedBackEventId:
{
MicsMasterVolumeLevel.MuteFeedback.FireUpdate();
break;
}
case DMOutputEventIds.Codec1LevelFeedBackEventId: case DMOutputEventIds.Codec1LevelFeedBackEventId:
{ {
if(Codec1VolumeLevel != null) if (Codec1VolumeLevel != null)
Codec1VolumeLevel.VolumeLevelFeedback.FireUpdate(); {
break; Codec1VolumeLevel.VolumeLevelFeedback.FireUpdate();
} Codec1VolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
}
break;
}
case DMOutputEventIds.Codec1MuteOnFeedBackEventId: case DMOutputEventIds.Codec1MuteOnFeedBackEventId:
{ {
if (Codec1VolumeLevel != null) if (Codec1VolumeLevel != null)
Codec1VolumeLevel.MuteFeedback.FireUpdate(); Codec1VolumeLevel.MuteFeedback.FireUpdate();
break; break;
} }
case DMOutputEventIds.Codec2LevelFeedBackEventId: case DMOutputEventIds.Codec2LevelFeedBackEventId:
{ {
if (Codec2VolumeLevel != null) if (Codec2VolumeLevel != null)
Codec2VolumeLevel.VolumeLevelFeedback.FireUpdate(); {
break; Codec2VolumeLevel.VolumeLevelFeedback.FireUpdate();
} Codec2VolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
}
break;
}
case DMOutputEventIds.Codec2MuteOnFeedBackEventId: case DMOutputEventIds.Codec2MuteOnFeedBackEventId:
{ {
if (Codec2VolumeLevel != null) if (Codec2VolumeLevel != null)
Codec2VolumeLevel.MuteFeedback.FireUpdate(); Codec2VolumeLevel.MuteFeedback.FireUpdate();
break; break;
} }
case DMOutputEventIds.MinVolumeFeedBackEventId:
{
Debug.Console(2, this, "MinVolumeFeedBackEventId: {0}", args.Index);
var level = MasterVolumeLevel as DmpsAudioOutputWithMixer;
if (level != null)
{
level.GetVolumeMin();
}
break;
}
case DMOutputEventIds.MaxVolumeFeedBackEventId:
{
Debug.Console(2, this, "MaxVolumeFeedBackEventId: {0}", args.Index);
var level = MasterVolumeLevel as DmpsAudioOutputWithMixer;
if (level != null)
{
level.GetVolumeMax();
}
break;
}
} }
} }
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{ {
var joinMap = new DmpsAudioOutputControllerJoinMap(joinStart); var joinMap = new DmpsAudioOutputControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); if (bridge != null)
{
if (!string.IsNullOrEmpty(joinMapSerialized)) bridge.AddJoinMap(Key, joinMap);
joinMap = JsonConvert.DeserializeObject<DmpsAudioOutputControllerJoinMap>(joinMapSerialized); }
else
if (bridge != null) {
{ Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
} }
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
@ -125,6 +180,11 @@ namespace PepperDash.Essentials.DM
if (MasterVolumeLevel != null) if (MasterVolumeLevel != null)
{ {
SetUpDmpsAudioOutputJoins(trilist, MasterVolumeLevel, joinMap.MasterVolumeLevel.JoinNumber); SetUpDmpsAudioOutputJoins(trilist, MasterVolumeLevel, joinMap.MasterVolumeLevel.JoinNumber);
var mixer = MasterVolumeLevel as DmpsAudioOutputWithMixer;
if (mixer != null)
{
trilist.SetUShortSigAction(joinMap.MixerPresetRecall.JoinNumber, mixer.RecallPreset);
}
} }
if (SourceVolumeLevel != null) if (SourceVolumeLevel != null)
@ -132,6 +192,11 @@ namespace PepperDash.Essentials.DM
SetUpDmpsAudioOutputJoins(trilist, SourceVolumeLevel, joinMap.SourceVolumeLevel.JoinNumber); SetUpDmpsAudioOutputJoins(trilist, SourceVolumeLevel, joinMap.SourceVolumeLevel.JoinNumber);
} }
if (MicsMasterVolumeLevel != null)
{
SetUpDmpsAudioOutputJoins(trilist, MicsMasterVolumeLevel, joinMap.MicsMasterVolumeLevel.JoinNumber);
}
if (Codec1VolumeLevel != null) if (Codec1VolumeLevel != null)
{ {
SetUpDmpsAudioOutputJoins(trilist, Codec1VolumeLevel, joinMap.Codec1VolumeLevel.JoinNumber); SetUpDmpsAudioOutputJoins(trilist, Codec1VolumeLevel, joinMap.Codec1VolumeLevel.JoinNumber);
@ -141,20 +206,20 @@ namespace PepperDash.Essentials.DM
{ {
SetUpDmpsAudioOutputJoins(trilist, Codec2VolumeLevel, joinMap.Codec2VolumeLevel.JoinNumber); SetUpDmpsAudioOutputJoins(trilist, Codec2VolumeLevel, joinMap.Codec2VolumeLevel.JoinNumber);
} }
} }
static void SetUpDmpsAudioOutputJoins(BasicTriList trilist, DmpsAudioOutput output, uint joinStart) static void SetUpDmpsAudioOutputJoins(BasicTriList trilist, DmpsAudioOutput output, uint joinStart)
{ {
var volumeLevelJoin = joinStart; var volumeLevelJoin = joinStart;
var volumeLevelScaledJoin = joinStart + 1;
var muteOnJoin = joinStart; var muteOnJoin = joinStart;
var muteOffJoin = joinStart + 1; var muteOffJoin = joinStart + 1;
var volumeUpJoin = joinStart + 2; var volumeUpJoin = joinStart + 2;
var volumeDownJoin = joinStart + 3; var volumeDownJoin = joinStart + 3;
var sendScaledVolumeJoin = joinStart + 4;
trilist.SetUShortSigAction(volumeLevelJoin, output.SetVolume);
output.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[volumeLevelJoin]); output.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[volumeLevelJoin]);
output.VolumeLevelScaledFeedback.LinkInputSig(trilist.UShortInput[volumeLevelScaledJoin]);
trilist.SetSigTrueAction(muteOnJoin, output.MuteOn); trilist.SetSigTrueAction(muteOnJoin, output.MuteOn);
output.MuteFeedback.LinkInputSig(trilist.BooleanInput[muteOnJoin]); output.MuteFeedback.LinkInputSig(trilist.BooleanInput[muteOnJoin]);
@ -163,30 +228,78 @@ namespace PepperDash.Essentials.DM
trilist.SetBoolSigAction(volumeUpJoin, output.VolumeUp); trilist.SetBoolSigAction(volumeUpJoin, output.VolumeUp);
trilist.SetBoolSigAction(volumeDownJoin, output.VolumeDown); trilist.SetBoolSigAction(volumeDownJoin, output.VolumeDown);
trilist.SetBoolSigAction(sendScaledVolumeJoin, output.SendScaledVolume);
trilist.SetUShortSigAction(volumeLevelJoin, output.SetVolume);
trilist.SetUShortSigAction(volumeLevelScaledJoin, output.SetVolumeScaled);
}
}
public class DmpsAudioOutputWithMixer : DmpsAudioOutput
{
CrestronControlSystem.Dmps3OutputMixerWithMonoAndStereo Mixer;
public DmpsAudioOutputWithMixer(Card.Dmps3OutputBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputMixerWithMonoAndStereo mixer)
: base(output, type)
{
Mixer = mixer;
GetVolumeMax();
GetVolumeMin();
}
public void GetVolumeMin()
{
MinLevel = (short)Mixer.MinVolumeFeedback.UShortValue;
if (VolumeLevelScaledFeedback != null)
{
VolumeLevelScaledFeedback.FireUpdate();
}
}
public void GetVolumeMax()
{
MaxLevel = (short)Mixer.MaxVolumeFeedback.UShortValue;
if (VolumeLevelScaledFeedback != null)
{
VolumeLevelScaledFeedback.FireUpdate();
}
}
public void RecallPreset(ushort preset)
{
Debug.Console(1, "DMPS Recalling Preset {0}", preset);
Mixer.PresetNumber.UShortValue = preset;
Mixer.RecallPreset();
} }
} }
public class DmpsAudioOutput : IBasicVolumeWithFeedback public class DmpsAudioOutput : IBasicVolumeWithFeedback
{ {
Card.Dmps3OutputBase Output; Card.Dmps3OutputBase Output;
eDmpsLevelType Type;
UShortInputSig Level; UShortInputSig Level;
eDmpsLevelType Type; private bool EnableVolumeSend;
private ushort VolumeLevelInput;
protected short MinLevel { get; set; }
protected short MaxLevel { get; set; }
public BoolFeedback MuteFeedback { get; private set; } public BoolFeedback MuteFeedback { get; private set; }
public IntFeedback VolumeLevelFeedback { get; private set; } public IntFeedback VolumeLevelFeedback { get; private set; }
public IntFeedback VolumeLevelScaledFeedback { get; private set; }
Action MuteOnAction; Action MuteOnAction;
Action MuteOffAction; Action MuteOffAction;
Action<bool> VolumeUpAction; Action<bool> VolumeUpAction;
Action<bool> VolumeDownAction; Action<bool> VolumeDownAction;
public DmpsAudioOutput(Card.Dmps3OutputBase output, eDmpsLevelType type) public DmpsAudioOutput(Card.Dmps3OutputBase output, eDmpsLevelType type)
{ {
Output = output; Output = output;
VolumeLevelInput = 0;
EnableVolumeSend = false;
Type = type; Type = type;
MinLevel = -800;
MaxLevel = 100;
switch (type) switch (type)
{ {
@ -194,14 +307,12 @@ namespace PepperDash.Essentials.DM
{ {
Level = output.MasterVolume; Level = output.MasterVolume;
MuteFeedback = new BoolFeedback( new Func<bool> (() => Output.MasterMuteOnFeedBack.BoolValue)); MuteFeedback = new BoolFeedback(new Func<bool>(() => Output.MasterMuteOnFeedBack.BoolValue));
VolumeLevelFeedback = new IntFeedback(new Func<int>(() => Output.MasterVolumeFeedBack.UShortValue)); VolumeLevelFeedback = new IntFeedback(new Func<int>(() => Output.MasterVolumeFeedBack.UShortValue));
MuteOnAction = new Action(Output.MasterMuteOn); MuteOnAction = new Action(Output.MasterMuteOn);
MuteOffAction = new Action(Output.MasterMuteOff); MuteOffAction = new Action(Output.MasterMuteOff);
VolumeUpAction = new Action<bool>((b) => Output.MasterVolumeUp.BoolValue = b); VolumeUpAction = new Action<bool>((b) => Output.MasterVolumeUp.BoolValue = b);
VolumeDownAction = new Action<bool>((b) => Output.MasterVolumeDown.BoolValue = b); VolumeDownAction = new Action<bool>((b) => Output.MasterVolumeDown.BoolValue = b);
break; break;
} }
case eDmpsLevelType.MicsMaster: case eDmpsLevelType.MicsMaster:
@ -214,7 +325,6 @@ namespace PepperDash.Essentials.DM
MuteOffAction = new Action(Output.MicMasterMuteOff); MuteOffAction = new Action(Output.MicMasterMuteOff);
VolumeUpAction = new Action<bool>((b) => Output.MicMasterLevelUp.BoolValue = b); VolumeUpAction = new Action<bool>((b) => Output.MicMasterLevelUp.BoolValue = b);
VolumeDownAction = new Action<bool>((b) => Output.MicMasterLevelDown.BoolValue = b); VolumeDownAction = new Action<bool>((b) => Output.MicMasterLevelDown.BoolValue = b);
break; break;
} }
case eDmpsLevelType.Source: case eDmpsLevelType.Source:
@ -243,7 +353,6 @@ namespace PepperDash.Essentials.DM
MuteOffAction = new Action(programOutput.Codec1MuteOff); MuteOffAction = new Action(programOutput.Codec1MuteOff);
VolumeUpAction = new Action<bool>((b) => programOutput.Codec1LevelUp.BoolValue = b); VolumeUpAction = new Action<bool>((b) => programOutput.Codec1LevelUp.BoolValue = b);
VolumeDownAction = new Action<bool>((b) => programOutput.Codec1LevelDown.BoolValue = b); VolumeDownAction = new Action<bool>((b) => programOutput.Codec1LevelDown.BoolValue = b);
} }
else else
{ {
@ -274,7 +383,6 @@ namespace PepperDash.Essentials.DM
MuteOffAction = new Action(programOutput.Codec2MuteOff); MuteOffAction = new Action(programOutput.Codec2MuteOff);
VolumeUpAction = new Action<bool>((b) => programOutput.Codec2LevelUp.BoolValue = b); VolumeUpAction = new Action<bool>((b) => programOutput.Codec2LevelUp.BoolValue = b);
VolumeDownAction = new Action<bool>((b) => programOutput.Codec2LevelDown.BoolValue = b); VolumeDownAction = new Action<bool>((b) => programOutput.Codec2LevelDown.BoolValue = b);
} }
else else
{ {
@ -292,7 +400,38 @@ namespace PepperDash.Essentials.DM
break; break;
} }
} }
if (VolumeLevelFeedback != null)
{
VolumeLevelScaledFeedback = new IntFeedback(new Func<int>(() => ScaleVolumeFeedback(VolumeLevelFeedback.UShortValue)));
VolumeLevelFeedback.FireUpdate();
VolumeLevelScaledFeedback.FireUpdate();
}
}
public void SetVolumeScaled(ushort level)
{
Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} level:{1} min:{2} max:{3}", Output.Name, level.ToString(), MinLevel.ToString(), MaxLevel.ToString());
VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel);
if (EnableVolumeSend == true)
{
Level.UShortValue = VolumeLevelInput;
}
}
public ushort ScaleVolumeFeedback(ushort level)
{
short signedLevel = (short)level;
Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} feedback:{1} min:{2} max:{3}", Output.Name, signedLevel.ToString(), MinLevel.ToString(), MaxLevel.ToString());
return (ushort)((signedLevel - MinLevel) * ushort.MaxValue / (MaxLevel - MinLevel));
}
public void SendScaledVolume(bool pressRelease)
{
EnableVolumeSend = pressRelease;
if (pressRelease == false)
{
SetVolumeScaled(VolumeLevelInput);
}
} }
#region IBasicVolumeWithFeedback Members #region IBasicVolumeWithFeedback Members

View file

@ -0,0 +1,192 @@
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.Bridges;
namespace PepperDash.Essentials.DM
{
/// <summary>
/// Exposes the volume levels for microphones DMPS3 chassis
/// </summary>
public class DmpsMicrophoneController
{
private Dictionary<uint, DmpsMicrophone> Mics;
public DmpsMicrophoneController(CrestronControlSystem dmps)
{
Debug.Console(2, "Creating Dmps Microphone Controller");
Mics = new Dictionary<uint,DmpsMicrophone>();
foreach (var mic in dmps.Microphones)
{
Debug.Console(0, "Dmps Microphone Controller Adding Mic: {0} Name: {1}", mic.ID, mic.Name);
var dmpsMic = new DmpsMicrophone("processor-microphone" + mic.ID, mic.Name, mic);
DeviceManager.AddDevice(dmpsMic);
Mics.Add(mic.ID, dmpsMic);
}
dmps.MicrophoneChange += new MicrophoneChangeEventHandler(Dmps_MicrophoneChange);
}
void Dmps_MicrophoneChange(MicrophoneBase mic, GenericEventArgs args)
{
Debug.Console(2, "Dmps Microphone Controller Index: {0} EventId: {1}", mic.ID, args.EventId.ToString());
if(Mics.ContainsKey(mic.ID))
{
Mics[mic.ID].Event(args.EventId);
}
}
}
public class DmpsMicrophone : EssentialsBridgeableDevice, IBasicVolumeWithFeedback
{
MicrophoneBase Mic;
private bool EnableVolumeSend;
private ushort VolumeLevelInput;
protected short MinLevel { get; set; }
protected short MaxLevel { get; set; }
public BoolFeedback MuteFeedback { get; private set; }
public IntFeedback VolumeLevelFeedback { get; private set; }
public IntFeedback VolumeLevelScaledFeedback { get; private set; }
public StringFeedback NameFeedback { get; private set; }
Action MuteOnAction;
Action MuteOffAction;
public DmpsMicrophone(string key, string name, MicrophoneBase mic) : base(key, name)
{
Mic = mic;
VolumeLevelInput = 0;
EnableVolumeSend = false;
MinLevel = 0;
MaxLevel = 600;
MuteFeedback = new BoolFeedback(new Func<bool>(() => Mic.MuteOnFeedBack.BoolValue));
VolumeLevelFeedback = new IntFeedback(new Func<int>(() => Mic.GainFeedBack.UShortValue));
VolumeLevelScaledFeedback = new IntFeedback(new Func<int>(() => ScaleVolumeFeedback(VolumeLevelFeedback.UShortValue)));
NameFeedback = new StringFeedback(new Func<string>(() => "Microphone " + Mic.ID));
MuteOnAction = new Action(Mic.MuteOn);
MuteOffAction = new Action(Mic.MuteOff);
VolumeLevelFeedback.FireUpdate();
VolumeLevelScaledFeedback.FireUpdate();
NameFeedback.FireUpdate();
MuteFeedback.FireUpdate();
}
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new DmpsMicrophoneControllerJoinMap(joinStart);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.MicGain.JoinNumber]);
VolumeLevelScaledFeedback.LinkInputSig(trilist.UShortInput[joinMap.MicGainScaled.JoinNumber ]);
MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.MicMuteOn.JoinNumber]);
MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.MicMuteOff.JoinNumber]);
NameFeedback.LinkInputSig(trilist.StringInput[joinMap.MicName.JoinNumber]);
trilist.SetUShortSigAction(joinMap.MicGain.JoinNumber, SetVolume);
trilist.SetUShortSigAction(joinMap.MicGainScaled.JoinNumber, SetVolumeScaled);
trilist.SetBoolSigAction(joinMap.MicGainScaledSend.JoinNumber, SendScaledVolume);
trilist.SetSigTrueAction(joinMap.MicMuteOn.JoinNumber, MuteOnAction);
trilist.SetSigTrueAction(joinMap.MicMuteOff.JoinNumber, MuteOffAction);
}
public void Event(int id)
{
if (id == MicrophoneEventIds.MuteOnFeedBackEventId)
{
MuteFeedback.FireUpdate();
}
else if (id == MicrophoneEventIds.GainFeedBackEventId)
{
VolumeLevelFeedback.FireUpdate();
VolumeLevelScaledFeedback.FireUpdate();
}
}
public void SetVolumeScaled(ushort level)
{
VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel);
if (EnableVolumeSend == true)
{
Mic.Gain.UShortValue = VolumeLevelInput;
}
}
public ushort ScaleVolumeFeedback(ushort level)
{
short signedLevel = (short)level;
return (ushort)((signedLevel - MinLevel) * ushort.MaxValue / (MaxLevel - MinLevel));
}
public void SendScaledVolume(bool pressRelease)
{
EnableVolumeSend = pressRelease;
if (pressRelease == false)
{
SetVolumeScaled(VolumeLevelInput);
}
}
#region IBasicVolumeWithFeedback Members
public void SetVolume(ushort level)
{
Mic.Gain.UShortValue = level;
}
public void MuteOn()
{
MuteOnAction();
}
public void MuteOff()
{
MuteOffAction();
}
#endregion
#region IBasicVolumeControls Members
public void VolumeUp(bool pressRelease)
{
}
public void VolumeDown(bool pressRelease)
{
}
public void MuteToggle()
{
if (MuteFeedback.BoolValue)
MuteOff();
else
MuteOn();
}
#endregion
}
}

View file

@ -25,6 +25,7 @@ namespace PepperDash.Essentials.DM
public CrestronControlSystem Dmps { get; set; } public CrestronControlSystem Dmps { get; set; }
public ISystemControl SystemControl { get; private set; } public ISystemControl SystemControl { get; private set; }
public bool? EnableRouting { get; private set; }
//Check if DMPS is a DMPS3-4K type for endpoint creation //Check if DMPS is a DMPS3-4K type for endpoint creation
public bool Dmps4kType { get; private set; } public bool Dmps4kType { get; private set; }
@ -32,9 +33,11 @@ namespace PepperDash.Essentials.DM
//IroutingNumericEvent //IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange; public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
//Feedback for DMPS System Power //Feedback for DMPS System Control
public BoolFeedback SystemPowerOnFeedback { get; private set; } public BoolFeedback SystemPowerOnFeedback { get; private set; }
public BoolFeedback SystemPowerOffFeedback { get; private set; } public BoolFeedback SystemPowerOffFeedback { get; private set; }
public BoolFeedback FrontPanelLockOnFeedback { get; private set; }
public BoolFeedback FrontPanelLockOffFeedback { get; private set; }
// Feedbacks for EssentialDM // Feedbacks for EssentialDM
public Dictionary<uint, IntFeedback> VideoOutputFeedbacks { get; private set; } public Dictionary<uint, IntFeedback> VideoOutputFeedbacks { get; private set; }
@ -59,6 +62,7 @@ namespace PepperDash.Essentials.DM
public Dictionary<uint, string> InputNames { get; set; } public Dictionary<uint, string> InputNames { get; set; }
public Dictionary<uint, string> OutputNames { get; set; } public Dictionary<uint, string> OutputNames { get; set; }
public Dictionary<uint, DmCardAudioOutputController> VolumeControls { get; private set; } public Dictionary<uint, DmCardAudioOutputController> VolumeControls { get; private set; }
public DmpsMicrophoneController Microphones { get; private set; }
public const int RouteOffTime = 500; public const int RouteOffTime = 500;
Dictionary<PortNumberType, CTimer> RouteOffTimers = new Dictionary<PortNumberType, CTimer>(); Dictionary<PortNumberType, CTimer> RouteOffTimers = new Dictionary<PortNumberType, CTimer>();
@ -122,26 +126,37 @@ namespace PepperDash.Essentials.DM
{ {
Dmps = Global.ControlSystem; Dmps = Global.ControlSystem;
switch (name.Replace("-", "").Replace("c", "").Replace("C", "")) switch (systemControl.SystemControlType)
{ {
case "dmps34k50": case eSystemControlType.Dmps34K150CSystemControl:
case "dmps34k100":
case "dmps34k150":
SystemControl = systemControl as Dmps34K150CSystemControl; SystemControl = systemControl as Dmps34K150CSystemControl;
Dmps4kType = true; Dmps4kType = true;
SystemPowerOnFeedback = new BoolFeedback(() => { return true; });
SystemPowerOffFeedback = new BoolFeedback(() => { return false; });
break; break;
case "dmps34k200": case eSystemControlType.Dmps34K200CSystemControl:
case "dmps34k250": case eSystemControlType.Dmps34K250CSystemControl:
case "dmps34k300": case eSystemControlType.Dmps34K300CSystemControl:
case "dmps34k350": case eSystemControlType.Dmps34K350CSystemControl:
SystemControl = systemControl as Dmps34K300CSystemControl; SystemControl = systemControl as Dmps34K300CSystemControl;
Dmps4kType = true; Dmps4kType = true;
SystemPowerOnFeedback = new BoolFeedback(() => { return true; });
SystemPowerOffFeedback = new BoolFeedback(() => { return false; });
break; break;
default: default:
SystemControl = systemControl as Dmps3SystemControl; SystemControl = systemControl as Dmps3SystemControl;
Dmps4kType = false; Dmps4kType = false;
SystemPowerOnFeedback = new BoolFeedback(() =>
{
return ((Dmps3SystemControl)SystemControl).SystemPowerOnFeedBack.BoolValue;
});
SystemPowerOffFeedback = new BoolFeedback(() =>
{
return ((Dmps3SystemControl)SystemControl).SystemPowerOffFeedBack.BoolValue;
});
break; break;
} }
Debug.Console(1, this, "DMPS Type = {0}, 4K Type = {1}", systemControl.SystemControlType, Dmps4kType);
InputPorts = new RoutingPortCollection<RoutingInputPort>(); InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>(); OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
@ -149,27 +164,13 @@ namespace PepperDash.Essentials.DM
TxDictionary = new Dictionary<uint, string>(); TxDictionary = new Dictionary<uint, string>();
RxDictionary = new Dictionary<uint, string>(); RxDictionary = new Dictionary<uint, string>();
SystemPowerOnFeedback = new BoolFeedback(() => FrontPanelLockOnFeedback = new BoolFeedback(() =>
{ {
if (SystemControl is Dmps3SystemControl) return SystemControl.FrontPanelLockOnFeedback.BoolValue;
{
return ((Dmps3SystemControl)SystemControl).SystemPowerOnFeedBack.BoolValue;
}
else
{
return false;
}
}); });
SystemPowerOffFeedback = new BoolFeedback(() => FrontPanelLockOffFeedback = new BoolFeedback(() =>
{ {
if (SystemControl is Dmps3SystemControl) return SystemControl.FrontPanelLockOffFeedback.BoolValue;
{
return ((Dmps3SystemControl)SystemControl).SystemPowerOffFeedBack.BoolValue;
}
else
{
return false;
}
}); });
VideoOutputFeedbacks = new Dictionary<uint, IntFeedback>(); VideoOutputFeedbacks = new Dictionary<uint, IntFeedback>();
@ -191,6 +192,8 @@ namespace PepperDash.Essentials.DM
SetupOutputCards(); SetupOutputCards();
SetupInputCards(); SetupInputCards();
Microphones = new DmpsMicrophoneController(Dmps);
} }
public override bool CustomActivate() public override bool CustomActivate()
@ -204,6 +207,41 @@ namespace PepperDash.Essentials.DM
Dmps.DMInputChange += Dmps_DMInputChange; Dmps.DMInputChange += Dmps_DMInputChange;
Dmps.DMOutputChange += Dmps_DMOutputChange; Dmps.DMOutputChange += Dmps_DMOutputChange;
Dmps.DMSystemChange += Dmps_DMSystemChange; Dmps.DMSystemChange += Dmps_DMSystemChange;
foreach (var x in VideoOutputFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in AudioOutputFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in VideoInputSyncFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in InputEndpointOnlineFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in InputNameFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in OutputNameFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in OutputEndpointOnlineFeedbacks)
{
x.Value.FireUpdate();
}
SystemPowerOnFeedback.FireUpdate();
SystemPowerOffFeedback.FireUpdate();
FrontPanelLockOnFeedback.FireUpdate();
FrontPanelLockOffFeedback.FireUpdate();
return base.CustomActivate(); return base.CustomActivate();
} }
@ -241,20 +279,10 @@ namespace PepperDash.Essentials.DM
} }
} }
public void SetPowerOn(bool a) public void SetRoutingEnable(bool enable)
{ {
if (SystemControl is Dmps3SystemControl) CrestronEnvironment.Sleep(1000);
{ EnableRouting = enable;
((Dmps3SystemControl)SystemControl).SystemPowerOn();
}
}
public void SetPowerOff(bool a)
{
if (SystemControl is Dmps3SystemControl)
{
((Dmps3SystemControl)SystemControl).SystemPowerOff();
}
} }
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
@ -277,20 +305,24 @@ namespace PepperDash.Essentials.DM
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
//Link up system //Link up system power only for non-4k DMPS3
trilist.SetBoolSigAction(joinMap.SystemPowerOn.JoinNumber, SetPowerOn); if (SystemControl is Dmps3SystemControl)
trilist.SetBoolSigAction(joinMap.SystemPowerOff.JoinNumber, SetPowerOff);
if (SystemPowerOnFeedback != null)
{ {
SystemPowerOnFeedback.LinkInputSig( trilist.SetBoolSigAction(joinMap.SystemPowerOn.JoinNumber, a => { if (a) { ((Dmps3SystemControl)SystemControl).SystemPowerOn(); } });
trilist.BooleanInput[joinMap.SystemPowerOn.JoinNumber]); trilist.SetBoolSigAction(joinMap.SystemPowerOff.JoinNumber, a => { if (a) { ((Dmps3SystemControl)SystemControl).SystemPowerOff(); } });
}
if (SystemPowerOffFeedback != null)
{
SystemPowerOffFeedback.LinkInputSig(
trilist.BooleanInput[joinMap.SystemPowerOff.JoinNumber]);
} }
SystemPowerOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SystemPowerOn.JoinNumber]);
SystemPowerOffFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SystemPowerOff.JoinNumber]);
trilist.SetBoolSigAction(joinMap.FrontPanelLockOn.JoinNumber, a => { if (a) {SystemControl.FrontPanelLockOn();}});
trilist.SetBoolSigAction(joinMap.FrontPanelLockOff.JoinNumber, a => { if (a) {SystemControl.FrontPanelLockOff();}});
FrontPanelLockOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.FrontPanelLockOn.JoinNumber]);
FrontPanelLockOffFeedback.LinkInputSig(trilist.BooleanInput[joinMap.FrontPanelLockOff.JoinNumber]);
trilist.SetBoolSigAction(joinMap.EnableRouting.JoinNumber, SetRoutingEnable);
// Link up outputs // Link up outputs
LinkInputsToApi(trilist, joinMap); LinkInputsToApi(trilist, joinMap);
LinkOutputsToApi(trilist, joinMap); LinkOutputsToApi(trilist, joinMap);
@ -351,6 +383,8 @@ namespace PepperDash.Essentials.DM
if (OutputNameFeedbacks[ioSlot] != null) if (OutputNameFeedbacks[ioSlot] != null)
{ {
OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]);
OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputVideoNames.JoinNumber + ioSlotJoin]);
OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputAudioNames.JoinNumber + ioSlotJoin]);
} }
if (OutputVideoRouteNameFeedbacks[ioSlot] != null) if (OutputVideoRouteNameFeedbacks[ioSlot] != null)
{ {
@ -372,6 +406,14 @@ namespace PepperDash.Essentials.DM
private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
{ {
if (Dmps4kType)
{
//DMPS-4K audio inputs 1-5 are aux inputs
for (uint i = 1; i <= 5; i++)
{
trilist.StringInput[joinMap.InputAudioNames.JoinNumber + i - 1].StringValue = String.Format("Aux Input {0}", i);
}
}
for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++) for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++)
{ {
Debug.Console(2, this, "Linking Input Card {0}", i); Debug.Console(2, this, "Linking Input Card {0}", i);
@ -379,15 +421,26 @@ namespace PepperDash.Essentials.DM
var ioSlot = i; var ioSlot = i;
var ioSlotJoin = ioSlot - 1; var ioSlotJoin = ioSlot - 1;
if (VideoInputSyncFeedbacks[ioSlot] != null) if (VideoInputSyncFeedbacks.ContainsKey(ioSlot) && VideoInputSyncFeedbacks[ioSlot] != null)
{ {
VideoInputSyncFeedbacks[ioSlot].LinkInputSig( VideoInputSyncFeedbacks[ioSlot].LinkInputSig(
trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]);
} }
if (InputNameFeedbacks[ioSlot] != null) if (InputNameFeedbacks.ContainsKey(ioSlot) && InputNameFeedbacks[ioSlot] != null)
{ {
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]);
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]);
if (Dmps4kType)
{
//DMPS-4K Audio Inputs are offset by 5
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin + 5]);
}
else
{
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]);
}
} }
trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s => trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s =>
@ -412,7 +465,7 @@ namespace PepperDash.Essentials.DM
}); });
if (InputEndpointOnlineFeedbacks[ioSlot] != null) if (InputEndpointOnlineFeedbacks.ContainsKey(ioSlot) && InputEndpointOnlineFeedbacks[ioSlot] != null)
{ {
InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]);
@ -463,7 +516,7 @@ namespace PepperDash.Essentials.DM
OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{ {
if (outputCard.NameFeedback != null && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
{ {
Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue); Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue);
return outputCard.NameFeedback.StringValue; return outputCard.NameFeedback.StringValue;
@ -509,14 +562,14 @@ namespace PepperDash.Essentials.DM
InputEndpointOnlineFeedbacks[inputCard.Number] = new BoolFeedback(() => inputCard.EndpointOnlineFeedback); InputEndpointOnlineFeedbacks[inputCard.Number] = new BoolFeedback(() => inputCard.EndpointOnlineFeedback);
if (inputCard.VideoDetectedFeedback != null) if (inputCard.VideoDetectedFeedback != null && inputCard.VideoDetectedFeedback.Supported)
{ {
VideoInputSyncFeedbacks[inputCard.Number] = new BoolFeedback(() => inputCard.VideoDetectedFeedback.BoolValue); VideoInputSyncFeedbacks[inputCard.Number] = new BoolFeedback(() => inputCard.VideoDetectedFeedback.BoolValue);
} }
InputNameFeedbacks[inputCard.Number] = new StringFeedback(() => InputNameFeedbacks[inputCard.Number] = new StringFeedback(() =>
{ {
if (inputCard.NameFeedback != null && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue)) if (inputCard.NameFeedback != null && inputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue))
{ {
Debug.Console(2, this, "Input Card {0} Name: {1}", inputCard.Number, inputCard.NameFeedback.StringValue); Debug.Console(2, this, "Input Card {0} Name: {1}", inputCard.Number, inputCard.NameFeedback.StringValue);
return inputCard.NameFeedback.StringValue; return inputCard.NameFeedback.StringValue;
@ -665,7 +718,7 @@ namespace PepperDash.Essentials.DM
{ {
AddAudioOnlyOutputPort(number, "Program"); AddAudioOnlyOutputPort(number, "Program");
var programOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase); var programOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput"), "Program Audio Output", outputCard as Card.Dmps3ProgramOutput);
DeviceManager.AddDevice(programOutput); DeviceManager.AddDevice(programOutput);
} }
@ -677,7 +730,7 @@ namespace PepperDash.Essentials.DM
{ {
AddAudioOnlyOutputPort(number, "Aux1"); AddAudioOnlyOutputPort(number, "Aux1");
var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase); var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux1Output);
DeviceManager.AddDevice(aux1Output); DeviceManager.AddDevice(aux1Output);
} }
@ -686,7 +739,7 @@ namespace PepperDash.Essentials.DM
{ {
AddAudioOnlyOutputPort(number, "Aux2"); AddAudioOnlyOutputPort(number, "Aux2");
var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase); var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux2Output);
DeviceManager.AddDevice(aux2Output); DeviceManager.AddDevice(aux2Output);
} }
@ -834,12 +887,17 @@ namespace PepperDash.Essentials.DM
{ {
Debug.Console(2, this, "DMOutputChange Output: {0} EventId: {1}", args.Number, args.EventId.ToString()); Debug.Console(2, this, "DMOutputChange Output: {0} EventId: {1}", args.Number, args.EventId.ToString());
if (args.EventId == DMOutputEventIds.OutputVuFeedBackEventId)
{
//Frequently called event that isn't needed
return;
}
var output = args.Number; var output = args.Number;
DMOutput outputCard = Dmps.SwitcherOutputs[output] as DMOutput; DMOutput outputCard = Dmps.SwitcherOutputs[output] as DMOutput;
if (args.EventId == DMOutputEventIds.VolumeEventId && if (args.EventId == DMOutputEventIds.VolumeEventId && VolumeControls.ContainsKey(output))
VolumeControls.ContainsKey(output))
{ {
VolumeControls[args.Number].VolumeEventFromChassis(); VolumeControls[args.Number].VolumeEventFromChassis();
} }
@ -904,15 +962,19 @@ namespace PepperDash.Essentials.DM
switch (args.EventId) switch (args.EventId)
{ {
case DMSystemEventIds.SystemPowerOnEventId: case DMSystemEventIds.SystemPowerOnEventId:
{
SystemPowerOnFeedback.FireUpdate();
break;
}
case DMSystemEventIds.SystemPowerOffEventId: case DMSystemEventIds.SystemPowerOffEventId:
{ {
SystemPowerOnFeedback.FireUpdate();
SystemPowerOffFeedback.FireUpdate(); SystemPowerOffFeedback.FireUpdate();
break; break;
} }
case DMSystemEventIds.FrontPanelLockOnEventId:
case DMSystemEventIds.FrontPanelLockOffEventId:
{
FrontPanelLockOnFeedback.FireUpdate();
FrontPanelLockOffFeedback.FireUpdate();
break;
}
} }
} }
@ -933,6 +995,10 @@ namespace PepperDash.Essentials.DM
{ {
try try
{ {
if (EnableRouting == false)
{
return;
}
Debug.Console(2, this, "Attempting a DM route from input {0} to output {1} {2}", inputSelector, outputSelector, sigType); Debug.Console(2, this, "Attempting a DM route from input {0} to output {1} {2}", inputSelector, outputSelector, sigType);

View file

@ -14,7 +14,7 @@ namespace PepperDash.Essentials.DM
{ {
[Description("Wrapper Class for DM-RMC-4K-Z-SCALER-C")] [Description("Wrapper Class for DM-RMC-4K-Z-SCALER-C")]
public class DmRmc4kZScalerCController : DmRmcControllerBase, IRmcRoutingWithFeedback, public class DmRmc4kZScalerCController : DmRmcControllerBase, IRmcRoutingWithFeedback,
IIROutputPorts, IComPorts, ICec IIROutputPorts, IComPorts, ICec, IRelayPorts
{ {
private readonly DmRmc4kzScalerC _rmc; private readonly DmRmc4kzScalerC _rmc;
@ -168,5 +168,18 @@ namespace PepperDash.Essentials.DM
} }
#endregion #endregion
#region Implementation of IRelayPorts
public CrestronCollection<Relay> RelayPorts
{
get { return _rmc.RelayPorts; }
}
public int NumberOfRelayPorts
{
get { return _rmc.NumberOfRelayPorts; }
}
#endregion
} }
} }

View file

@ -61,6 +61,7 @@ namespace PepperDash.Essentials.DM
Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
rmc.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); rmc.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = rmc.Name;
if (rmc.VideoOutputResolutionFeedback != null) if (rmc.VideoOutputResolutionFeedback != null)
rmc.VideoOutputResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentOutputResolution.JoinNumber]); rmc.VideoOutputResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentOutputResolution.JoinNumber]);
if (rmc.EdidManufacturerFeedback != null) if (rmc.EdidManufacturerFeedback != null)

View file

@ -263,6 +263,7 @@ namespace PepperDash.Essentials.DM
tx.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber]); tx.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber]);
tx.AnyVideoInput.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentInputResolution.JoinNumber]); tx.AnyVideoInput.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentInputResolution.JoinNumber]);
trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber].UShortValue = (ushort)tx.HdcpSupportCapability; trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber].UShortValue = (ushort)tx.HdcpSupportCapability;
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = tx.Name;
bool hdcpTypeSimple; bool hdcpTypeSimple;

View file

@ -93,6 +93,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="AirMedia\AirMediaPropertiesConfig.cs" /> <Compile Include="AirMedia\AirMediaPropertiesConfig.cs" />
<Compile Include="AirMedia\AirMediaController.cs" /> <Compile Include="AirMedia\AirMediaController.cs" />
<Compile Include="Chassis\DmpsMicrophoneController.cs" />
<Compile Include="Chassis\DmBladeChassisController.cs" /> <Compile Include="Chassis\DmBladeChassisController.cs" />
<Compile Include="Chassis\DmCardAudioOutput.cs" /> <Compile Include="Chassis\DmCardAudioOutput.cs" />
<Compile Include="Chassis\DmChassisController.cs" /> <Compile Include="Chassis\DmChassisController.cs" />

View file

@ -69,6 +69,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("directoryResults")] [JsonProperty("directoryResults")]
public List<DirectoryItem> CurrentDirectoryResults { get; private set; } public List<DirectoryItem> CurrentDirectoryResults { get; private set; }
[JsonProperty("contacts")]
public List<DirectoryItem> Contacts public List<DirectoryItem> Contacts
{ {
get get
@ -77,6 +78,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
} }
} }
[JsonProperty("folders")]
public List<DirectoryItem> Folders public List<DirectoryItem> Folders
{ {
get get

View file

@ -124,6 +124,8 @@
<Compile Include="Cameras\CameraControl.cs" /> <Compile Include="Cameras\CameraControl.cs" />
<Compile Include="Display\PanasonicThDisplay.cs" /> <Compile Include="Display\PanasonicThDisplay.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingInfo.cs" /> <Compile Include="VideoCodec\Interfaces\IHasMeetingInfo.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingLock.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingRecording.cs" />
<Compile Include="VideoCodec\Interfaces\IHasParticipants.cs" /> <Compile Include="VideoCodec\Interfaces\IHasParticipants.cs" />
<Compile Include="VideoCodec\Interfaces\IHasPresentationOnlyMeeting.cs" /> <Compile Include="VideoCodec\Interfaces\IHasPresentationOnlyMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" /> <Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" />

View file

@ -19,7 +19,7 @@ namespace PepperDash.Essentials.Devices.Common
public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingOutputs public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingOutputs
{ {
public IrOutputPortController IrPort { get; private set; } public IrOutputPortController IrPort { get; private set; }
public const string StandardDriverName = "Apple AppleTV-v2.ir"; public const string StandardDriverName = "Apple_AppleTV_4th_Gen_Essentials.ir";
public uint DisplayUiType { get { return DisplayUiConstants.TypeAppleTv; } } public uint DisplayUiType { get { return DisplayUiConstants.TypeAppleTv; } }
public AppleTV(string key, string name, IrOutputPortController portCont) public AppleTV(string key, string name, IrOutputPortController portCont)

View file

@ -6,6 +6,8 @@ using Crestron.SimplSharp;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.VideoCodec namespace PepperDash.Essentials.Devices.Common.VideoCodec
{ {
/// <summary> /// <summary>
@ -25,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary> /// </summary>
public interface IHasZoomRoomLayouts : IHasCodecLayouts public interface IHasZoomRoomLayouts : IHasCodecLayouts
{ {
event EventHandler<LayoutInfoChangedEventArgs> AvailableLayoutsChanged; event EventHandler<LayoutInfoChangedEventArgs> LayoutInfoChanged;
BoolFeedback LayoutViewIsOnFirstPageFeedback { get; } // TODO: #697 [*] Consider modifying to report button visibility in func BoolFeedback LayoutViewIsOnFirstPageFeedback { get; } // TODO: #697 [*] Consider modifying to report button visibility in func
BoolFeedback LayoutViewIsOnLastPageFeedback { get; } // TODO: #697 [*] Consider modifying to report button visibility in func BoolFeedback LayoutViewIsOnLastPageFeedback { get; } // TODO: #697 [*] Consider modifying to report button visibility in func
@ -45,6 +47,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public class LayoutInfoChangedEventArgs : EventArgs public class LayoutInfoChangedEventArgs : EventArgs
{ {
[JsonProperty("availableLayouts", NullValueHandling = NullValueHandling.Ignore)]
public ZoomRoom.zConfiguration.eLayoutStyle AvailableLayouts { get; set; } public ZoomRoom.zConfiguration.eLayoutStyle AvailableLayouts { get; set; }
[JsonProperty("currentSelectedLayout", NullValueHandling = NullValueHandling.Ignore)]
public ZoomRoom.zConfiguration.eLayoutStyle CurrentSelectedLayout { get; set; }
[JsonProperty("canSwapContentWithThumbnail", NullValueHandling = NullValueHandling.Ignore)]
public bool CanSwapContentWithThumbnail { get; set; }
[JsonProperty("contentSwappedWithThumbnail", NullValueHandling = NullValueHandling.Ignore)]
public bool ContentSwappedWithThumbnail { get; set; }
[JsonProperty("layoutViewIsOnFirstPage", NullValueHandling = NullValueHandling.Ignore)]
public bool LayoutViewIsOnFirstPage { get; set; }
[JsonProperty("layoutViewIsOnLastPage", NullValueHandling = NullValueHandling.Ignore)]
public bool LayoutViewIsOnLastPage { get; set; }
} }
} }

View file

@ -24,24 +24,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary> /// </summary>
public class MeetingInfo public class MeetingInfo
{ {
[JsonProperty("id")] [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public string Id { get; private set; } public string Id { get; private set; }
[JsonProperty("name")] [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; private set; } public string Name { get; private set; }
[JsonProperty("host")] [JsonProperty("host", NullValueHandling = NullValueHandling.Ignore)]
public string Host { get; private set; } public string Host { get; private set; }
[JsonProperty("password")] [JsonProperty("password", NullValueHandling = NullValueHandling.Ignore)]
public string Password { get; private set; } public string Password { get; private set; }
[JsonProperty("shareStatus")] [JsonProperty("shareStatus", NullValueHandling = NullValueHandling.Ignore)]
public string ShareStatus { get; private set; } public string ShareStatus { get; private set; }
[JsonProperty("isHost")] [JsonProperty("isHost", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsHost { get; private set; } public Boolean IsHost { get; private set; }
[JsonProperty("isSharingMeeting")] [JsonProperty("isSharingMeeting", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsSharingMeeting { get; private set; } public Boolean IsSharingMeeting { get; private set; }
[JsonProperty("waitingForHost")] [JsonProperty("waitingForHost", NullValueHandling = NullValueHandling.Ignore)]
public Boolean WaitingForHost { get; private set; } public Boolean WaitingForHost { get; private set; }
[JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsLocked { get; private set; }
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost)
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked)
{ {
Id = id; Id = id;
Name = name; Name = name;
@ -51,6 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
IsHost = isHost; IsHost = isHost;
IsSharingMeeting = isSharingMeeting; IsSharingMeeting = isSharingMeeting;
WaitingForHost = waitingForHost; WaitingForHost = waitingForHost;
IsLocked = isLocked;
} }
} }

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
public interface IHasMeetingLock
{
BoolFeedback MeetingIsLockedFeedback { get; }
void LockMeeting();
void UnLockMeeting();
void ToggleMeetingLock();
}
}

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
public interface IHasMeetingRecording
{
BoolFeedback MeetingIsRecordingFeedback { get; }
void StartRecording();
void StopRecording();
void ToggleRecording();
}
}

View file

@ -12,6 +12,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
public interface IHasParticipants public interface IHasParticipants
{ {
CodecParticipants Participants { get; } CodecParticipants Participants { get; }
/// <summary>
/// Removes the participant from the meeting
/// </summary>
/// <param name="participant"></param>
void RemoveParticipant(int userId);
/// <summary>
/// Sets the participant as the new host
/// </summary>
/// <param name="participant"></param>
void SetParticipantAsHost(int userId);
} }
/// <summary> /// <summary>
@ -29,6 +41,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary> /// </summary>
public interface IHasParticipantAudioMute : IHasParticipantVideoMute public interface IHasParticipantAudioMute : IHasParticipantVideoMute
{ {
/// <summary>
/// Mute audio of all participants
/// </summary>
void MuteAudioForAllParticipants();
void MuteAudioForParticipant(int userId); void MuteAudioForParticipant(int userId);
void UnmuteAudioForParticipant(int userId); void UnmuteAudioForParticipant(int userId);
void ToggleAudioForParticipant(int userId); void ToggleAudioForParticipant(int userId);

View file

@ -4,6 +4,8 @@ using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec namespace PepperDash.Essentials.Devices.Common.Codec
{ {
/// <summary> /// <summary>
@ -19,12 +21,19 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary> /// </summary>
public abstract class VideoCodecInfo public abstract class VideoCodecInfo
{ {
[JsonProperty("multiSiteOptionIsEnabled", NullValueHandling = NullValueHandling.Ignore)]
public abstract bool MultiSiteOptionIsEnabled { get; } public abstract bool MultiSiteOptionIsEnabled { get; }
[JsonProperty("ipAddress", NullValueHandling = NullValueHandling.Ignore)]
public abstract string IpAddress { get; } public abstract string IpAddress { get; }
[JsonProperty("sipPhoneNumber", NullValueHandling = NullValueHandling.Ignore)]
public abstract string SipPhoneNumber { get; } public abstract string SipPhoneNumber { get; }
[JsonProperty("e164Alias", NullValueHandling = NullValueHandling.Ignore)]
public abstract string E164Alias { get; } public abstract string E164Alias { get; }
[JsonProperty("h323Id", NullValueHandling = NullValueHandling.Ignore)]
public abstract string H323Id { get; } public abstract string H323Id { get; }
[JsonProperty("sipUri", NullValueHandling = NullValueHandling.Ignore)]
public abstract string SipUri { get; } public abstract string SipUri { get; }
[JsonProperty("autoAnswerEnabled", NullValueHandling = NullValueHandling.Ignore)]
public abstract bool AutoAnswerEnabled { get; } public abstract bool AutoAnswerEnabled { get; }
} }
} }

View file

@ -431,8 +431,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
m.MinutesBeforeMeeting = 5; m.MinutesBeforeMeeting = 5;
m.Id = i.ToString(); m.Id = i.ToString();
m.Organizer = "Employee " + 1; m.Organizer = "Employee " + 1;
m.StartTime = DateTime.Now.AddMinutes(6).AddHours(i); m.StartTime = DateTime.Now.AddMinutes(5).AddHours(i);
m.EndTime = DateTime.Now.AddHours(i).AddMinutes(16); m.EndTime = DateTime.Now.AddHours(i).AddMinutes(50);
m.Title = "Meeting " + i; m.Title = "Meeting " + i;
m.Calls.Add(new Call() { Number = i + "meeting@fake.com"}); m.Calls.Add(new Call() { Number = i + "meeting@fake.com"});
_CodecSchedule.Meetings.Add(m); _CodecSchedule.Meetings.Add(m);
@ -602,6 +602,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn); CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn);
SupportsCameraAutoMode = true;
CameraAutoModeIsOnFeedback.FireUpdate(); CameraAutoModeIsOnFeedback.FireUpdate();
DeviceManager.AddDevice(internalCamera); DeviceManager.AddDevice(internalCamera);
@ -609,7 +611,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
NearEndPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco NearEndPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco
NearEndPresets = PropertiesConfig.Presets; if (PropertiesConfig.Presets != null && PropertiesConfig.Presets.Count > 0)
{
NearEndPresets = PropertiesConfig.Presets;
}
else
{
for (int i = 1; i <= NearEndPresets.Capacity; i++)
{
var label = string.Format("Near End Preset {0}", i);
NearEndPresets.Add(new CodecRoomPreset(i, label, true, false));
}
}
FarEndRoomPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco FarEndRoomPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco

View file

@ -18,5 +18,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
[JsonProperty("presets")] [JsonProperty("presets")]
public List<CodecRoomPreset> Presets { get; set; } public List<CodecRoomPreset> Presets { get; set; }
public MockVcPropertiesConfig()
{
Favorites = new List<CodecActiveCallItem>();
Presets = new List<CodecRoomPreset>();
}
} }
} }

View file

@ -41,6 +41,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
SharingSourceFeedback = new StringFeedback(SharingSourceFeedbackFunc); SharingSourceFeedback = new StringFeedback(SharingSourceFeedbackFunc);
SharingContentIsOnFeedback = new BoolFeedback(SharingContentIsOnFeedbackFunc); SharingContentIsOnFeedback = new BoolFeedback(SharingContentIsOnFeedbackFunc);
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
MeetingsToDisplayFeedback = new IntFeedback(() => MeetingsToDisplay);
InputPorts = new RoutingPortCollection<RoutingInputPort>(); InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>(); OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
@ -305,8 +308,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.OnlineStatusChange += (device, args) => trilist.OnlineStatusChange += (device, args) =>
{ {
if (!args.DeviceOnLine) return; if (!args.DeviceOnLine) return;
trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC");
}; };
} }
@ -425,7 +426,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
if (codec is IHasCameraAutoMode) if (codec is IHasCameraAutoMode)
{ {
trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, SupportsCameraAutoMode);
(codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate();
} }
@ -598,6 +599,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
UpdateParticipantsXSig(codec, trilist, joinMap); UpdateParticipantsXSig(codec, trilist, joinMap);
}; };
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.CurrentParticipants.JoinNumber, "\xFC");
UpdateParticipantsXSig(codec, trilist, joinMap);
};
} }
private void UpdateParticipantsXSig(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void UpdateParticipantsXSig(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
@ -829,7 +839,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
UpdateMeetingsList(codec, trilist, joinMap); UpdateMeetingsList(codec, trilist, joinMap);
} }
}; };
}
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
trilist.SetUShortSigAction(joinMap.MeetingsToDisplay.JoinNumber, m => MeetingsToDisplay = m);
MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]);
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC");
UpdateMeetingsList(codec, trilist, joinMap);
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]);
};
}
private void UpdateMeetingsList(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void UpdateMeetingsList(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{ {
@ -850,19 +875,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
var meetingsData = UpdateMeetingsListXSig(_currentMeetings); var meetingsData = UpdateMeetingsListXSig(_currentMeetings);
trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData);
trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count); trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count);
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC");
UpdateMeetingsListXSig(_currentMeetings);
};
} }
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
private int _meetingsToDisplay = 3;
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
protected int MeetingsToDisplay
{
get { return _meetingsToDisplay; }
set {
_meetingsToDisplay = (ushort) (value == 0 ? 3 : value);
MeetingsToDisplayFeedback.FireUpdate();
}
}
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
public IntFeedback MeetingsToDisplayFeedback { get; set; }
private string UpdateMeetingsListXSig(List<Meeting> meetings) private string UpdateMeetingsListXSig(List<Meeting> meetings)
{ {
const int maxMeetings = 3; // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
//const int _meetingsToDisplay = 3;
const int maxDigitals = 2; const int maxDigitals = 2;
const int maxStrings = 7; const int maxStrings = 7;
const int offset = maxDigitals + maxStrings; const int offset = maxDigitals + maxStrings;
var digitalIndex = maxStrings * maxMeetings; //15 var digitalIndex = maxStrings * _meetingsToDisplay; //15
var stringIndex = 0; var stringIndex = 0;
var meetingIndex = 0; var meetingIndex = 0;
var tokenArray = new XSigToken[maxMeetings * offset]; var tokenArray = new XSigToken[_meetingsToDisplay * offset];
/* /*
* Digitals * Digitals
* IsJoinable - 1 * IsJoinable - 1
@ -885,7 +936,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
if (meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue; if (meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue;
if (meetingIndex >= maxMeetings * offset) if (meetingIndex >= _meetingsToDisplay * offset)
{ {
Debug.Console(2, this, "Max Meetings reached"); Debug.Console(2, this, "Max Meetings reached");
break; break;
@ -910,10 +961,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
stringIndex += maxStrings; stringIndex += maxStrings;
} }
while (meetingIndex < maxMeetings * offset) while (meetingIndex < _meetingsToDisplay * offset)
{ {
Debug.Console(2, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}", Debug.Console(2, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}",
meetingIndex, maxMeetings * offset); meetingIndex, _meetingsToDisplay * offset);
//digitals //digitals
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false);
@ -980,6 +1031,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
}; };
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC");
UpdateDirectoryXSig(codec.CurrentDirectoryResult,
!codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
};
} }
@ -1207,80 +1268,88 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig());
trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count); trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count);
}; };
var joinCodec = this as IJoinCalls; var joinCodec = this as IJoinCalls;
if (joinCodec != null) if (joinCodec != null)
{ {
trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls()); trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls());
for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++) for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++)
{ {
trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () => trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () =>
{ {
var call = ActiveCalls[i]; var call = ActiveCalls[i];
if (call != null) if (call != null)
{ {
joinCodec.JoinCall(call); joinCodec.JoinCall(call);
} }
else else
{ {
Debug.Console(0, this, "[Join Call] Unable to find call at index '{0}'", i); Debug.Console(0, this, "[Join Call] Unable to find call at index '{0}'", i);
} }
}); });
} }
} }
var holdCodec = this as IHasCallHold; var holdCodec = this as IHasCallHold;
if (holdCodec != null) if (holdCodec != null)
{ {
trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () => trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () =>
{ {
foreach (var call in ActiveCalls) foreach (var call in ActiveCalls)
{ {
holdCodec.HoldCall(call); holdCodec.HoldCall(call);
} }
}); });
for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++) for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++)
{ {
var index = i; var index = i;
trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () => trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () =>
{ {
if (index < 0 || index >= ActiveCalls.Count) return; if (index < 0 || index >= ActiveCalls.Count) return;
var call = ActiveCalls[index]; var call = ActiveCalls[index];
if (call != null) if (call != null)
{ {
holdCodec.HoldCall(call); holdCodec.HoldCall(call);
} }
else else
{ {
Debug.Console(0, this, "[Hold Call] Unable to find call at index '{0}'", i); Debug.Console(0, this, "[Hold Call] Unable to find call at index '{0}'", i);
} }
}); });
trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () => trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () =>
{ {
if (index < 0 || index >= ActiveCalls.Count) return; if (index < 0 || index >= ActiveCalls.Count) return;
var call = ActiveCalls[index]; var call = ActiveCalls[index];
if (call != null) if (call != null)
{ {
holdCodec.ResumeCall(call); holdCodec.ResumeCall(call);
} }
else else
{ {
Debug.Console(0, this, "[Resume Call] Unable to find call at index '{0}'", i); Debug.Console(0, this, "[Resume Call] Unable to find call at index '{0}'", i);
} }
}); });
} }
} }
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC");
UpdateCallStatusXSig();
};
} }
private string UpdateCallStatusXSig() private string UpdateCallStatusXSig()
@ -1664,6 +1733,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.UShortOutput[joinMap.CameraPresetSelect.JoinNumber].UShortValue, String.Empty); trilist.UShortOutput[joinMap.CameraPresetSelect.JoinNumber].UShortValue, String.Empty);
trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000); trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000);
}); });
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.CameraPresetNames.JoinNumber, "\xFC");
SetCameraPresetNames(presetCodec.NearEndPresets);
};
} }
// Following fields only used for Bridging // Following fields only used for Bridging

View file

@ -618,13 +618,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private bool _can_Switch_Speaker_View; private bool _can_Switch_Speaker_View;
private bool _can_Switch_Wall_View; private bool _can_Switch_Wall_View;
private bool _can_Switch_Share_On_All_Screens; private bool _can_Switch_Share_On_All_Screens;
private bool _can_Switch_Floating_Share_Content;
private bool _is_In_First_Page; private bool _is_In_First_Page;
private bool _is_In_Last_Page; private bool _is_In_Last_Page;
private string _video_type; private string _video_type;
public bool can_Adjust_Floating_Video { get; set; } public bool can_Adjust_Floating_Video { get; set; }
public bool can_Switch_Floating_Share_Content { get; set; }
public bool can_Switch_Floating_Share_Content
{
get
{
return _can_Switch_Floating_Share_Content;
}
set
{
if (value != _can_Switch_Floating_Share_Content)
{
_can_Switch_Floating_Share_Content = value;
NotifyPropertyChanged("can_Switch_Floating_Share_Content");
}
}
}
/// <summary> /// <summary>
/// [on/off] // Set to On if it is possible to invoke zConfiguration Call Layout Style: ShareAll, to switch to the ShareAll mode, where the content sharing is shown full screen on all monitors. /// [on/off] // Set to On if it is possible to invoke zConfiguration Call Layout Style: ShareAll, to switch to the ShareAll mode, where the content sharing is shown full screen on all monitors.
@ -744,12 +762,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
} }
public class CallRecordInfo public class CallRecordInfo : NotifiableObject
{ {
private bool _meetingIsBeingRecorded;
public bool canRecord { get; set; } public bool canRecord { get; set; }
public bool emailRequired { get; set; } public bool emailRequired { get; set; }
public bool amIRecording { get; set; } public bool amIRecording { get; set; }
public bool meetingIsBeingRecorded { get; set; }
public bool meetingIsBeingRecorded
{
get
{
return _meetingIsBeingRecorded;
}
set
{
if (value != _meetingIsBeingRecorded)
{
_meetingIsBeingRecorded = value;
NotifyPropertyChanged("meetingIsBeingRecorded");
}
}
}
} }
} }
@ -1123,9 +1158,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
} }
public class Lock public class Lock : NotifiableObject
{ {
public bool Enable { get; set; } private bool _enable;
public bool Enable
{
get
{
return _enable;
}
set
{
if (value != _enable)
{
_enable = value;
NotifyPropertyChanged("Enable");
}
}
}
} }
public class ClosedCaption public class ClosedCaption

View file

@ -26,13 +26,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
IRouting, IRouting,
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting,
IHasMeetingLock, IHasMeetingRecording
{ {
private const long MeetingRefreshTimer = 60000; private const long MeetingRefreshTimer = 60000;
public uint DefaultMeetingDurationMin { get; private set; } public uint DefaultMeetingDurationMin { get; private set; }
private const string Delimiter = "\x0D\x0A"; /// <summary>
/// CR LF
/// </summary>
private const string EchoDelimiter = "\x0D\x0A\x0D\x0A";
private const string SendDelimiter = "\x0D";
/// <summary>
/// CR LF } CR LF
/// </summary>
private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A";
private string[] Delimiters = new string[] { EchoDelimiter, JsonDelimiter, "OK\x0D\x0A", "end\x0D\x0A" };
//"echo off\x0D\x0A\x0A\x0D\x0A"
private readonly GenericQueue _receiveQueue; private readonly GenericQueue _receiveQueue;
//private readonly CrestronQueue<string> _receiveQueue; //private readonly CrestronQueue<string> _receiveQueue;
@ -58,7 +71,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_props = JsonConvert.DeserializeObject<ZoomRoomPropertiesConfig>(config.Properties.ToString()); _props = JsonConvert.DeserializeObject<ZoomRoomPropertiesConfig>(config.Properties.ToString());
_receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512); _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 2048);
Communication = comm; Communication = comm;
@ -70,7 +83,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
else else
{ {
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000,
"zStatus SystemUnit\r"); "zStatus SystemUnit" + SendDelimiter);
} }
DeviceManager.AddDevice(CommunicationMonitor); DeviceManager.AddDevice(CommunicationMonitor);
@ -85,9 +98,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted; _syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted;
_syncState.FirstJsonResponseReceived += (o, a) => SetUpSyncQueries();
PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync");
PortGather = new CommunicationGather(Communication, "\x0A") {IncludeDelimiter = true}; PhonebookSyncState.InitialSyncCompleted += (o, a) => ResubscribeForAddedContacts();
PortGather = new CommunicationGather(Communication, Delimiters) {IncludeDelimiter = true};
PortGather.LineReceived += Port_LineReceived; PortGather.LineReceived += Port_LineReceived;
CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd,
@ -147,6 +164,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc); ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc);
NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc); NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc);
MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable );
MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded );
} }
public CommunicationGather PortGather { get; private set; } public CommunicationGather PortGather { get; private set; }
@ -499,19 +520,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
var sharingStatus = GetSharingStatus(); var sharingStatus = GetSharingStatus();
MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false); MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue);
return; return;
} }
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None", var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None",
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost); MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(1, this, "Error processing state property update. {0}", e.Message); Debug.Console(1, this, "Error processing state property update. {0}", e.Message);
Debug.Console(2, this, e.StackTrace); Debug.Console(2, this, e.StackTrace);
MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false); MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue);
} }
} }
@ -578,11 +599,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
case "ShareThumb": case "ShareThumb":
{ {
ContentSwappedWithThumbnailFeedback.FireUpdate(); ContentSwappedWithThumbnailFeedback.FireUpdate();
OnLayoutInfoChanged();
break; break;
} }
case "Style": case "Style":
{ {
LocalLayoutFeedback.FireUpdate(); LocalLayoutFeedback.FireUpdate();
OnLayoutInfoChanged();
break; break;
} }
case "Size": case "Size":
@ -597,6 +620,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
}; };
Configuration.Call.Lock.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "Enable")
{
MeetingIsLockedFeedback.FireUpdate();
MeetingInfo = new MeetingInfo
(
MeetingInfo.Id,
MeetingInfo.Name,
MeetingInfo.Host,
MeetingInfo.Password,
GetSharingStatus(),
MeetingInfo.IsHost,
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue
);
}
};
// This is to deal with incorrect object structure coming back from the Zoom Room on v 5.6.3 // This is to deal with incorrect object structure coming back from the Zoom Room on v 5.6.3
Configuration.Client.Call.Layout.PropertyChanged += (o, a) => Configuration.Client.Call.Layout.PropertyChanged += (o, a) =>
{ {
@ -613,11 +656,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
case "ShareThumb": case "ShareThumb":
{ {
ContentSwappedWithThumbnailFeedback.FireUpdate(); ContentSwappedWithThumbnailFeedback.FireUpdate();
OnLayoutInfoChanged();
break; break;
} }
case "Style": case "Style":
{ {
LocalLayoutFeedback.FireUpdate(); LocalLayoutFeedback.FireUpdate();
OnLayoutInfoChanged();
break; break;
} }
} }
@ -634,13 +679,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Status.Call.PropertyChanged += (o, a) => Status.Call.PropertyChanged += (o, a) =>
{ {
if (a.PropertyName == "Info") switch(a.PropertyName)
{
case "Info":
{ {
Debug.Console(1, this, "Updating Call Status"); Debug.Console(1, this, "Updating Call Status");
UpdateCallStatus(); UpdateCallStatus();
break;
} }
case "Status":
{
UpdateCallStatus();
break;
}
}
}; };
Status.Call.CallRecordInfo.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "meetingIsBeingRecorded")
{
MeetingIsRecordingFeedback.FireUpdate();
}
};
Status.Sharing.PropertyChanged += (o, a) => Status.Sharing.PropertyChanged += (o, a) =>
{ {
switch (a.PropertyName) switch (a.PropertyName)
@ -663,7 +726,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
return; return;
} }
// Update the share status of the meeting info // Update the share status of the meeting info
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost); var meetingInfo = new MeetingInfo(MeetingInfo.Id,
MeetingInfo.Name,
MeetingInfo.Host,
MeetingInfo.Password,
GetSharingStatus(),
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
break; break;
} }
@ -714,13 +785,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
LayoutViewIsOnLastPageFeedback.FireUpdate(); LayoutViewIsOnLastPageFeedback.FireUpdate();
break; break;
} }
//case "video_type": case "can_Switch_Floating_Share_Content":
// { {
// It appears as though the actual value we want to watch is Configuration.Call.Layout.Style CanSwapContentWithThumbnailFeedback.FireUpdate();
// LocalLayoutFeedback.FireUpdate(); break;
// break; }
// }
} }
OnLayoutInfoChanged();
}; };
Status.NumberOfScreens.PropertyChanged += (o, a) => Status.NumberOfScreens.PropertyChanged += (o, a) =>
@ -849,7 +920,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Debug.Console(1, this, "Sending: '{0}'", command); Debug.Console(1, this, "Sending: '{0}'", command);
} }
Communication.SendText(command + Delimiter); Communication.SendText(command + SendDelimiter);
} }
/// <summary> /// <summary>
@ -859,13 +930,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <param name="args"></param> /// <param name="args"></param>
private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
{ {
//if (CommDebuggingIsOn) //Debug.Console(0, this, "Port_LineReceived");
// Debug.Console(1, this, "Gathered: '{0}'", args.Text);
_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage)); if (args.Delimiter != JsonDelimiter)
{
// Debug.Console(0, this,
//@"Non JSON response:
//Delimiter: {0}
//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text);
ProcessNonJsonResponse(args.Text);
return;
}
else
{
// Debug.Console(0, this,
//@"JSON response:
//Delimiter: {0}
//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text);
_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, DeserializeResponse));
//_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage));
}
} }
/// <summary> /// <summary>
/// Queues the initial queries to be sent upon connection /// Queues the initial queries to be sent upon connection
/// </summary> /// </summary>
@ -924,6 +1010,93 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncState.StartSync(); _syncState.StartSync();
} }
private void SetupSession()
{
// disable echo of commands
SendText("echo off");
// switch to json format
// set feedback exclusions
// Currently the feedback exclusions don't work when using the API in JSON response mode
// But leave these here in case the API gets updated in the future
// These may work as of 5.9.4
// In 5.9.4 we're getting sent an AddedContact message for every contact in the phonebook on connect, which is redunant and way too much data
// We want to exclude these messages right away until after we've retrieved the entire phonebook and then we can re-enable them
SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
SendText("zStatus SystemUnit");
}
/// <summary>
/// Removes the feedback exclusion for added contacts
/// </summary>
private void ResubscribeForAddedContacts()
{
SendText("zFeedback Register Op: in Path: /Event/Phonebook/AddedContact");
}
/// <summary>
/// Processes non-JSON responses as their are received
/// </summary>
/// <param name="response"></param>
private void ProcessNonJsonResponse(string response)
{
if (response.Contains("client_loop: send disconnect: Broken pipe"))
{
Debug.Console(1, this, Debug.ErrorLogLevel.Error,
"Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected.");
return;
}
if (!_syncState.InitialSyncComplete)
{
if(response.ToLower().Contains("*r login successful"))
{
_syncState.LoginResponseReceived();
SendText("format json");
SetupSession();
}
//switch (response.Trim().ToLower()) // remove the whitespace
//{
// case "*r login successful":
// {
// _syncState.LoginMessageReceived();
// //// Fire up a thread to send the intial commands.
// //CrestronInvoke.BeginInvoke(o =>
// //{
// // disable echo of commands
// SendText("echo off");
// // switch to json format
// SendText("format json");
// // set feedback exclusions
// // Currently the feedback exclusions don't work when using the API in JSON response mode
// // But leave these here in case the API gets updated in the future
// // These may work as of 5.9.4
// if (_props.DisablePhonebookAutoDownload)
// {
// SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
// }
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list");
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list");
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
// //});
// break;
// }
//}
}
}
/// <summary> /// <summary>
/// Processes messages as they are dequeued /// Processes messages as they are dequeued
/// </summary> /// </summary>
@ -951,7 +1124,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
//Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); //Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter);
if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + EchoDelimiter)
// Check for the beginning of a new JSON message // Check for the beginning of a new JSON message
{ {
_jsonFeedbackMessageIsIncoming = true; _jsonFeedbackMessageIsIncoming = true;
@ -968,7 +1141,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
return; return;
} }
if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + EchoDelimiter)
// Check for the end of a JSON message // Check for the end of a JSON message
{ {
_jsonMessage.Append(message); _jsonMessage.Append(message);
@ -1013,7 +1186,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
case "*r login successful": case "*r login successful":
{ {
_syncState.LoginMessageReceived(); _syncState.LoginResponseReceived();
// Fire up a thread to send the intial commands. // Fire up a thread to send the intial commands.
@ -1035,7 +1208,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
Thread.Sleep(100); Thread.Sleep(100);
if (!_props.DisablePhonebookAutoDownload) if (_props.DisablePhonebookAutoDownload)
{ {
SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
} }
@ -1066,6 +1239,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var message = JObject.Parse(trimmedResponse); var message = JObject.Parse(trimmedResponse);
if (!_syncState.FirstJsonResponseWasReceived)
{
_syncState.ReceivedFirstJsonResponse();
}
var eType = var eType =
(eZoomRoomResponseType) (eZoomRoomResponseType)
Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value<string>(), true); Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value<string>(), true);
@ -1074,7 +1252,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var responseObj = message[topKey]; var responseObj = message[topKey];
Debug.Console(1, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString()); Debug.Console(1, this, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString().Replace("\n", CrestronEnvironment.NewLine));
switch (eType) switch (eType)
{ {
@ -1244,7 +1422,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Participants.CurrentParticipants = participants; Participants.CurrentParticipants = participants;
// Update the share status of the meeting info // Update the share status of the meeting info
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus, GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost); var meetingInfo = new MeetingInfo(
MeetingInfo.Id,
MeetingInfo.Name,
Participants.Host.Name,
MeetingInfo.Password,
MeetingInfo.ShareStatus,
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
PrintCurrentCallParticipants(); PrintCurrentCallParticipants();
@ -1446,21 +1633,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
Status.NeedWaitForHost = JsonConvert.DeserializeObject<zEvent.NeedWaitForHost>(responseObj.ToString()); Status.NeedWaitForHost = JsonConvert.DeserializeObject<zEvent.NeedWaitForHost>(responseObj.ToString());
Debug.Console(1, this, "NeedWaitForHost: {0}", Status.NeedWaitForHost.Wait); Debug.Console(1, this, "WaitingForHost: {0}", Status.NeedWaitForHost.Wait);
if (Status.NeedWaitForHost.Wait) if (Status.NeedWaitForHost.Wait)
{ {
if (MeetingInfo == null) if (MeetingInfo == null)
{ {
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true); GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue);
UpdateCallStatus(); UpdateCallStatus();
break; break;
} }
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true); GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue);
UpdateCallStatus(); UpdateCallStatus();
@ -1470,12 +1657,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (MeetingInfo == null) if (MeetingInfo == null)
{ {
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, false); GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue);
break; break;
} }
MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password,
GetSharingStatus(), GetIsHostMyself(), false, false); GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue);
break; break;
} }
@ -1559,7 +1746,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (result.Success) if (result.Success)
{ {
MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost); MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue);
break; break;
} }
@ -1578,19 +1765,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
case "login": case "login":
{ {
_syncState.LoginMessageReceived(); _syncState.LoginResponseReceived();
if (!_syncState.InitialQueryMessagesWereSent) SetupSession();
{
SetUpSyncQueries();
}
JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); JsonConvert.PopulateObject(responseObj.ToString(), Status.Login);
break; break;
} }
case "systemunit": case "systemunit":
{ {
JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit);
break; break;
@ -1904,6 +2089,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetSharingStatus(), GetSharingStatus(),
GetIsHostMyself(), GetIsHostMyself(),
!String.Equals(Status.Call.Info.meeting_type,"NORMAL"), !String.Equals(Status.Call.Info.meeting_type,"NORMAL"),
false,
MeetingIsLockedFeedback.BoolValue
);
}
// TODO [ ] Issue #868
else if (item.Status == eCodecCallStatus.Disconnected)
{
MeetingInfo = new MeetingInfo(
string.Empty,
string.Empty,
string.Empty,
string.Empty,
string.Empty,
false,
false,
false,
false false
); );
} }
@ -2132,16 +2333,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var layoutsCodec = this as IHasZoomRoomLayouts; var layoutsCodec = this as IHasZoomRoomLayouts;
if (layoutsCodec != null) if (layoutsCodec != null)
{ {
layoutsCodec.AvailableLayoutsChanged += (o, a) => layoutsCodec.LayoutInfoChanged += (o, a) =>
{ {
trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber,
== zConfiguration.eLayoutStyle.Gallery == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery));
(a.AvailableLayouts &
zConfiguration.eLayoutStyle.Gallery)); trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber,
trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker zConfiguration.eLayoutStyle.Speaker == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Speaker));
==
(a.AvailableLayouts &
zConfiguration.eLayoutStyle.Speaker));
trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip
== ==
(a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip)); (a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip));
@ -2196,7 +2397,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
trilist.SetUShortSigAction(joinMap.ScreenIndexToPinUserTo.JoinNumber, (u) => ScreenIndexToPinUserTo = u); trilist.SetUShortSigAction(joinMap.ScreenIndexToPinUserTo.JoinNumber, (u) => ScreenIndexToPinUserTo = u);
} }
// TODO: #714 [ ] LinkZoomRoomToApi >> layoutSizeCoodec
var layoutSizeCodec = this as IHasSelfviewSize; var layoutSizeCodec = this as IHasSelfviewSize;
if (layoutSizeCodec != null) if (layoutSizeCodec != null)
{ {
@ -2218,6 +2418,75 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
layoutSizeCodec.SelfviewPipSizeFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetSelfviewPipSize.JoinNumber]); layoutSizeCodec.SelfviewPipSizeFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetSelfviewPipSize.JoinNumber]);
} }
PasswordRequired += (device, args) =>
{
if (args.LoginAttemptCancelled)
{
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false);
return;
}
if (!string.IsNullOrEmpty(args.Message))
{
trilist.SetString(joinMap.PasswordPromptMessage.JoinNumber, args.Message);
}
if (args.LoginAttemptFailed)
{
trilist.SetBool(joinMap.PasswordLoginFailed.JoinNumber, true);
return;
}
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, true);
};
MeetingInfoChanged += (device, args) =>
{
trilist.SetString(joinMap.MeetingInfoId.JoinNumber, args.Info.Id);
trilist.SetString(joinMap.MeetingInfoHost.JoinNumber, args.Info.Host);
trilist.SetString(joinMap.MeetingInfoPassword.JoinNumber, args.Info.Password);
trilist.SetBool(joinMap.IsHost.JoinNumber, args.Info.IsHost);
trilist.SetBool(joinMap.ShareOnlyMeeting.JoinNumber, args.Info.IsSharingMeeting);
trilist.SetBool(joinMap.WaitingForHost.JoinNumber, args.Info.WaitingForHost);
//trilist.SetString(joinMap.CurrentSource.JoinNumber, args.Info.ShareStatus);
};
trilist.SetSigTrueAction(joinMap.StartMeetingNow.JoinNumber, () => StartMeeting(0));
trilist.SetSigTrueAction(joinMap.ShareOnlyMeeting.JoinNumber, StartSharingOnlyMeeting);
trilist.SetSigTrueAction(joinMap.StartNormalMeetingFromSharingOnlyMeeting.JoinNumber, StartNormalMeetingFromSharingOnlyMeeting);
// not sure if this would be needed here, should be handled by VideoCodecBase.cs LinkToApi methods
//DirectoryResultReturned += (device, args) =>
//{
// // add logic here if necessary when event fires
//};
trilist.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword);
PasswordRequired += (devices, args) =>
{
if (args.LoginAttemptCancelled)
{
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false);
return;
}
if (!string.IsNullOrEmpty(args.Message))
{
trilist.SetString(joinMap.PasswordPromptMessage.JoinNumber, args.Message);
}
if (args.LoginAttemptFailed)
{
// login attempt failed
return;
}
trilist.SetBool(joinMap.PasswordIncorrect.JoinNumber, args.LastAttemptWasIncorrect);
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, true);
};
trilist.OnlineStatusChange += (device, args) => trilist.OnlineStatusChange += (device, args) =>
{ {
if (!args.DeviceOnLine) return; if (!args.DeviceOnLine) return;
@ -2334,6 +2603,56 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
} }
/// <summary>
/// Invites contacts to a new meeting for a specified duration
/// </summary>
/// <param name="contacts"></param>
/// <param name="duration"></param>
public void InviteContactsToNewMeeting(List<InvitableDirectoryContact> contacts, uint duration)
{
if(duration == 0)
{
duration = DefaultMeetingDurationMin;
}
StringBuilder message = new StringBuilder();
// Add the prefix
message.Append(string.Format("zCommand Invite Duration: {0}", duration));
// Add each invitee
foreach (var contact in contacts)
{
var invitee = string.Format(" user: {0}", contact.ContactId);
message.Append(invitee);
}
SendText(message.ToString());
}
/// <summary>
/// Invites contacts to an existing meeting
/// </summary>
/// <param name="contacts"></param>
public void InviteContactsToExistingMeeting(List<InvitableDirectoryContact> contacts)
{
StringBuilder message = new StringBuilder();
// Add the prefix
message.Append(string.Format("zCommand Call Invite"));
// Add each invitee
foreach (var contact in contacts)
{
var invitee = string.Format(" user: {0}", contact.ContactId);
message.Append(invitee);
}
SendText(message.ToString());
}
/// <summary> /// <summary>
/// Starts a PMI Meeting for the specified duration (or default meeting duration if 0 is specified) /// Starts a PMI Meeting for the specified duration (or default meeting duration if 0 is specified)
@ -2469,10 +2788,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public CodecParticipants Participants { get; private set; } public CodecParticipants Participants { get; private set; }
public void RemoveParticipant(int userId)
{
SendText(string.Format("zCommand Call Expel Id: {0}", userId));
}
public void SetParticipantAsHost(int userId)
{
SendText(string.Format("zCommand Call HostChange Id: {0}", userId));
}
#endregion #endregion
#region IHasParticipantAudioMute Members #region IHasParticipantAudioMute Members
public void MuteAudioForAllParticipants()
{
SendText(string.Format("zCommand Call MuteAll Mute: on"));
}
public void MuteAudioForParticipant(int userId) public void MuteAudioForParticipant(int userId)
{ {
SendText(string.Format("zCommand Call MuteParticipant Mute: on Id: {0}", userId)); SendText(string.Format("zCommand Call MuteParticipant Mute: on Id: {0}", userId));
@ -2770,7 +3104,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
#region IHasZoomRoomLayouts Members #region IHasZoomRoomLayouts Members
public event EventHandler<LayoutInfoChangedEventArgs> AvailableLayoutsChanged; public event EventHandler<LayoutInfoChangedEventArgs> LayoutInfoChanged;
private Func<bool> LayoutViewIsOnFirstPageFeedbackFunc private Func<bool> LayoutViewIsOnFirstPageFeedbackFunc
{ {
@ -2836,15 +3170,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Debug.Console(1, this, "availablelayouts: {0}", availableLayouts); Debug.Console(1, this, "availablelayouts: {0}", availableLayouts);
var handler = AvailableLayoutsChanged;
if (handler != null)
{
handler(this, new LayoutInfoChangedEventArgs() {AvailableLayouts = availableLayouts});
}
AvailableLayouts = availableLayouts; AvailableLayouts = availableLayouts;
} }
private void OnLayoutInfoChanged()
{
var handler = LayoutInfoChanged;
if (handler != null)
{
handler(this, new LayoutInfoChangedEventArgs()
{
AvailableLayouts = AvailableLayouts,
CurrentSelectedLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle),string.IsNullOrEmpty(LocalLayoutFeedback.StringValue) ? "None" : LocalLayoutFeedback.StringValue , true),
LayoutViewIsOnFirstPage = LayoutViewIsOnFirstPageFeedback.BoolValue,
LayoutViewIsOnLastPage = LayoutViewIsOnLastPageFeedback.BoolValue,
CanSwapContentWithThumbnail = CanSwapContentWithThumbnailFeedback.BoolValue,
ContentSwappedWithThumbnail = ContentSwappedWithThumbnailFeedback.BoolValue,
});
}
}
public void GetAvailableLayouts() public void GetAvailableLayouts()
{ {
SendText("zStatus Call Layout"); SendText("zStatus Call Layout");
@ -3034,7 +3379,63 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
#endregion #endregion
}
#region IHasMeetingLock Members
public BoolFeedback MeetingIsLockedFeedback { get; private set; }
public void LockMeeting()
{
SendText(string.Format("zConfiguration Call Lock Enable: on"));
}
public void UnLockMeeting()
{
SendText(string.Format("zConfiguration Call Lock Enable: off"));
}
public void ToggleMeetingLock()
{
if (MeetingIsLockedFeedback.BoolValue)
{
UnLockMeeting();
}
else
{
LockMeeting();
}
}
#endregion
#region IHasMeetingRecording Members
public BoolFeedback MeetingIsRecordingFeedback { get; private set; }
public void StartRecording()
{
SendText(string.Format("Command Call Record Enable: on"));
}
public void StopRecording()
{
SendText(string.Format("Command Call Record Enable: off"));
}
public void ToggleRecording()
{
if (MeetingIsRecordingFeedback.BoolValue)
{
StopRecording();
}
else
{
StartRecording();
}
}
#endregion
}
/// <summary> /// <summary>
/// Zoom Room specific info object /// Zoom Room specific info object
@ -3047,8 +3448,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Configuration = configuration; Configuration = configuration;
} }
[JsonIgnore]
public ZoomRoomStatus Status { get; private set; } public ZoomRoomStatus Status { get; private set; }
public ZoomRoomConfiguration Configuration { get; private set; } [JsonIgnore]
public ZoomRoomConfiguration Configuration { get; private set; }
public override bool AutoAnswerEnabled public override bool AutoAnswerEnabled
{ {
@ -3155,7 +3558,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
} }
public bool LoginMessageWasReceived { get; private set; } public bool LoginResponseWasReceived { get; private set; }
public bool FirstJsonResponseWasReceived { get; private set; }
public bool InitialQueryMessagesWereSent { get; private set; } public bool InitialQueryMessagesWereSent { get; private set; }
@ -3171,6 +3576,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public event EventHandler<EventArgs> InitialSyncCompleted; public event EventHandler<EventArgs> InitialSyncCompleted;
public event EventHandler FirstJsonResponseReceived;
public void StartSync() public void StartSync()
{ {
DequeueQueries(); DequeueQueries();
@ -3193,14 +3600,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncQueries.Enqueue(query); _syncQueries.Enqueue(query);
} }
public void LoginMessageReceived() public void LoginResponseReceived()
{ {
LoginMessageWasReceived = true; LoginResponseWasReceived = true;
Debug.Console(1, this, "Login Message Received."); Debug.Console(1, this, "Login Rsponse Received.");
CheckSyncStatus(); CheckSyncStatus();
} }
private void InitialQueryMessagesSent() public void ReceivedFirstJsonResponse()
{
FirstJsonResponseWasReceived = true;
Debug.Console(1, this, "First JSON Response Received.");
var handler = FirstJsonResponseReceived;
if (handler != null)
{
handler(this, null);
}
CheckSyncStatus();
}
public void InitialQueryMessagesSent()
{ {
InitialQueryMessagesWereSent = true; InitialQueryMessagesWereSent = true;
Debug.Console(1, this, "Query Messages Sent."); Debug.Console(1, this, "Query Messages Sent.");
@ -3224,7 +3644,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public void CodecDisconnected() public void CodecDisconnected()
{ {
_syncQueries.Clear(); _syncQueries.Clear();
LoginMessageWasReceived = false; LoginResponseWasReceived = false;
FirstJsonResponseWasReceived = false;
InitialQueryMessagesWereSent = false; InitialQueryMessagesWereSent = false;
LastQueryResponseWasReceived = false; LastQueryResponseWasReceived = false;
CamerasHaveBeenSetUp = false; CamerasHaveBeenSetUp = false;
@ -3233,7 +3654,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void CheckSyncStatus() private void CheckSyncStatus()
{ {
if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && if (LoginResponseWasReceived && FirstJsonResponseWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived &&
CamerasHaveBeenSetUp) CamerasHaveBeenSetUp)
{ {
InitialSyncComplete = true; InitialSyncComplete = true;

View file

@ -1,301 +1,496 @@
using System; using System;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges.JoinMaps; using PepperDash.Essentials.Core.Bridges.JoinMaps;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
public class ZoomRoomJoinMap : VideoCodecControllerJoinMap public class ZoomRoomJoinMap : VideoCodecControllerJoinMap
{ {
#region Digital #region Digital
[JoinName("CanSwapContentWithThumbnail")] // TODO [ ] Issue #868
public JoinDataComplete CanSwapContentWithThumbnail = new JoinDataComplete( [JoinName("ShowPasswordPrompt")]
new JoinData public JoinDataComplete ShowPasswordPrompt = new JoinDataComplete(
{ new JoinData
JoinNumber = 206, {
JoinSpan = 1 JoinNumber = 6,
}, JoinSpan = 1
new JoinMetadata },
{ new JoinMetadata
Description = "FB Indicates if content can be swapped with thumbnail", {
JoinCapabilities = eJoinCapabilities.ToSIMPL, Description = "FB Indicates to show the password prompt",
JoinType = eJoinType.Digital JoinCapabilities = eJoinCapabilities.ToSIMPL,
}); JoinType = eJoinType.Digital
});
[JoinName("SwapContentWithThumbnail")]
public JoinDataComplete SwapContentWithThumbnail = new JoinDataComplete( // TODO [ ] Issue #868
new JoinData [JoinName("PasswordIncorrect")]
{ public JoinDataComplete PasswordIncorrect = new JoinDataComplete(
JoinNumber = 206, new JoinData
JoinSpan = 1 {
}, JoinNumber = 7,
new JoinMetadata JoinSpan = 1
{ },
Description = "Pulse to swap content with thumbnail. FB reports current state", new JoinMetadata
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, {
JoinType = eJoinType.Digital Description = "FB Indicates the password entered is incorrect",
}); JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
[JoinName("GetAvailableLayouts")] });
public JoinDataComplete GetAvailableLayouts = new JoinDataComplete(
new JoinData // TODO [ ] Issue #868
{ [JoinName("PassowrdLoginFailed")]
JoinNumber = 215, public JoinDataComplete PasswordLoginFailed = new JoinDataComplete(
JoinSpan = 1 new JoinData
}, {
new JoinMetadata JoinNumber = 8,
{ JoinSpan = 1
Description = "Gets the available layouts. Will update the LayoutXXXXXIsAvailbale signals.", },
JoinCapabilities = eJoinCapabilities.FromSIMPL, new JoinMetadata
JoinType = eJoinType.Digital {
}); Description = "FB Indicates the password entered is incorrect",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
[JoinName("LayoutIsOnFirstPage")] JoinType = eJoinType.Digital
public JoinDataComplete LayoutIsOnFirstPage = new JoinDataComplete( });
new JoinData
{ // TODO [ ] Issue #868
JoinNumber = 216, [JoinName("WaitingForHost")]
JoinSpan = 1 public JoinDataComplete WaitingForHost = new JoinDataComplete(
}, new JoinData
new JoinMetadata {
{ JoinNumber = 9,
Description = "Indicates if layout is on first page", JoinSpan = 1
JoinCapabilities = eJoinCapabilities.ToSIMPL, },
JoinType = eJoinType.Digital new JoinMetadata
}); {
Description = "FB Indicates system is waiting for host",
[JoinName("LayoutIsOnLastPage")] JoinCapabilities = eJoinCapabilities.ToSIMPL,
public JoinDataComplete LayoutIsOnLastPage = new JoinDataComplete( JoinType = eJoinType.Digital
new JoinData });
{
JoinNumber = 217, // TODO [ ] Issue #868
JoinSpan = 1 [JoinName("IsHost")]
}, public JoinDataComplete IsHost = new JoinDataComplete(
new JoinMetadata new JoinData
{ {
Description = "Indicates if layout is on first page", JoinNumber = 10,
JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinSpan = 1
JoinType = eJoinType.Digital },
}); new JoinMetadata
{
[JoinName("LayoutTurnToNextPage")] Description = "FB Indicates system is the host",
public JoinDataComplete LayoutTurnToNextPage = new JoinDataComplete( JoinCapabilities = eJoinCapabilities.ToSIMPL,
new JoinData JoinType = eJoinType.Digital
{ });
JoinNumber = 216,
JoinSpan = 1 // TODO [ ] Issue #868
}, [JoinName("StartMeetingNow")]
new JoinMetadata public JoinDataComplete StartMeetingNow = new JoinDataComplete(
{ new JoinData
Description = "Turns layout view to next page", {
JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinNumber = 25,
JoinType = eJoinType.Digital JoinSpan = 1
}); },
new JoinMetadata
[JoinName("LayoutTurnToPreviousPage")] {
public JoinDataComplete LayoutTurnToPreviousPage = new JoinDataComplete( Description = "FB Indicates the password prompt is active",
new JoinData JoinCapabilities = eJoinCapabilities.FromSIMPL,
{ JoinType = eJoinType.Digital
JoinNumber = 217, });
JoinSpan = 1
}, // TODO [ ] Issue #868
new JoinMetadata [JoinName("ShareOnlyMeeting")]
{ public JoinDataComplete ShareOnlyMeeting = new JoinDataComplete(
Description = "Turns layout view to previous page", new JoinData
JoinCapabilities = eJoinCapabilities.FromSIMPL, {
JoinType = eJoinType.Digital JoinNumber = 26,
}); JoinSpan = 1
},
[JoinName("LayoutGalleryIsAvailable")] new JoinMetadata
public JoinDataComplete LayoutGalleryIsAvailable = new JoinDataComplete( {
new JoinData Description = "Triggers a share only meeting, feedback indicates the current meeting is share only",
{ JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinNumber = 221, JoinType = eJoinType.Digital
JoinSpan = 1 });
},
new JoinMetadata // TODO [ ] Issue #868
{ [JoinName("StartNormalMeetingFromSharingOnlyMeeting")]
Description = "FB Indicates if layout 'Gallery' is available", public JoinDataComplete StartNormalMeetingFromSharingOnlyMeeting = new JoinDataComplete(
JoinCapabilities = eJoinCapabilities.ToSIMPL, new JoinData
JoinType = eJoinType.DigitalSerial {
}); JoinNumber = 27,
JoinSpan = 1
[JoinName("LayoutSpeakerIsAvailable")] },
public JoinDataComplete LayoutSpeakerIsAvailable = new JoinDataComplete( new JoinMetadata
new JoinData {
{ Description = "Starts a normal meeting from a share only meeting",
JoinNumber = 222, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinSpan = 1 JoinType = eJoinType.Digital
}, });
new JoinMetadata
{ [JoinName("CanSwapContentWithThumbnail")]
Description = "FB Indicates if layout 'Speaker' is available", public JoinDataComplete CanSwapContentWithThumbnail = new JoinDataComplete(
JoinCapabilities = eJoinCapabilities.ToSIMPL, new JoinData
JoinType = eJoinType.DigitalSerial {
}); JoinNumber = 206,
JoinSpan = 1
[JoinName("LayoutStripIsAvailable")] },
public JoinDataComplete LayoutStripIsAvailable = new JoinDataComplete( new JoinMetadata
new JoinData {
{ Description = "FB Indicates if content can be swapped with thumbnail",
JoinNumber = 223, JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinSpan = 1 JoinType = eJoinType.Digital
}, });
new JoinMetadata
{ [JoinName("SwapContentWithThumbnail")]
Description = "FB Indicates if layout 'Strip' is available", public JoinDataComplete SwapContentWithThumbnail = new JoinDataComplete(
JoinCapabilities = eJoinCapabilities.ToSIMPL, new JoinData
JoinType = eJoinType.DigitalSerial {
}); JoinNumber = 206,
JoinSpan = 1
[JoinName("LayoutShareAllIsAvailable")] },
public JoinDataComplete LayoutShareAllIsAvailable = new JoinDataComplete( new JoinMetadata
new JoinData {
{ Description = "Pulse to swap content with thumbnail. FB reports current state",
JoinNumber = 224, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinSpan = 1 JoinType = eJoinType.Digital
}, });
new JoinMetadata
{ [JoinName("GetAvailableLayouts")]
Description = "FB Indicates if layout 'ShareAll' is available", public JoinDataComplete GetAvailableLayouts = new JoinDataComplete(
JoinCapabilities = eJoinCapabilities.ToSIMPL, new JoinData
JoinType = eJoinType.DigitalSerial {
}); JoinNumber = 215,
JoinSpan = 1
// TODO: #714 [ ] JoinMap >> SelfivewPipSizeToggle },
[JoinName("SelfviewPipSizeToggle")] new JoinMetadata
public JoinDataComplete SelfviewPipSizeToggle = new JoinDataComplete( {
new JoinData Description = "Gets the available layouts. Will update the LayoutXXXXXIsAvailbale signals.",
{ JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinNumber = 231, JoinType = eJoinType.Digital
JoinSpan = 1 });
},
new JoinMetadata [JoinName("LayoutIsOnFirstPage")]
{ public JoinDataComplete LayoutIsOnFirstPage = new JoinDataComplete(
Description = "Toggles the selfview pip size, (aka layout size)", new JoinData
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, {
JoinType = eJoinType.Digital JoinNumber = 216,
}); JoinSpan = 1
},
//[JoinName("ParticipantAudioMuteToggleStart")] new JoinMetadata
//public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( {
// new JoinData Description = "Indicates if layout is on first page",
// { JoinCapabilities = eJoinCapabilities.ToSIMPL,
// JoinNumber = 500, JoinType = eJoinType.Digital
// JoinSpan = 100 });
// },
// new JoinMetadata [JoinName("LayoutIsOnLastPage")]
// { public JoinDataComplete LayoutIsOnLastPage = new JoinDataComplete(
// Description = "Toggles the participant's audio mute status", new JoinData
// JoinCapabilities = eJoinCapabilities.ToSIMPL, {
// JoinType = eJoinType.Digital JoinNumber = 217,
// }); JoinSpan = 1
},
//[JoinName("ParticipantVideoMuteToggleStart")] new JoinMetadata
//public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( {
// new JoinData Description = "Indicates if layout is on first page",
// { JoinCapabilities = eJoinCapabilities.ToSIMPL,
// JoinNumber = 800, JoinType = eJoinType.Digital
// JoinSpan = 100 });
// },
// new JoinMetadata [JoinName("LayoutTurnToNextPage")]
// { public JoinDataComplete LayoutTurnToNextPage = new JoinDataComplete(
// Description = "Toggles the participant's video mute status", new JoinData
// JoinCapabilities = eJoinCapabilities.ToSIMPL, {
// JoinType = eJoinType.Digital JoinNumber = 216,
// }); JoinSpan = 1
},
//[JoinName("ParticipantPinToggleStart")] new JoinMetadata
//public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( {
// new JoinData Description = "Turns layout view to next page",
// { JoinCapabilities = eJoinCapabilities.FromSIMPL,
// JoinNumber = 1100, JoinType = eJoinType.Digital
// JoinSpan = 100 });
// },
// new JoinMetadata [JoinName("LayoutTurnToPreviousPage")]
// { public JoinDataComplete LayoutTurnToPreviousPage = new JoinDataComplete(
// Description = "Toggles the participant's pin status", new JoinData
// JoinCapabilities = eJoinCapabilities.ToSIMPL, {
// JoinType = eJoinType.Digital JoinNumber = 217,
// }); JoinSpan = 1
},
#endregion new JoinMetadata
{
Description = "Turns layout view to previous page",
#region Analog JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
[JoinName("NumberOfScreens")] });
public JoinDataComplete NumberOfScreens = new JoinDataComplete(
new JoinData [JoinName("LayoutGalleryIsAvailable")]
{ public JoinDataComplete LayoutGalleryIsAvailable = new JoinDataComplete(
JoinNumber = 11, new JoinData
JoinSpan = 1 {
}, JoinNumber = 221,
new JoinMetadata JoinSpan = 1
{ },
Description = "Reports the number of screens connected", new JoinMetadata
JoinCapabilities = eJoinCapabilities.ToSIMPL, {
JoinType = eJoinType.Analog Description = "FB Indicates if layout 'Gallery' is available",
}); JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.DigitalSerial
[JoinName("ScreenIndexToPinUserTo")] });
public JoinDataComplete ScreenIndexToPinUserTo = new JoinDataComplete(
new JoinData [JoinName("LayoutSpeakerIsAvailable")]
{ public JoinDataComplete LayoutSpeakerIsAvailable = new JoinDataComplete(
JoinNumber = 11, new JoinData
JoinSpan = 1 {
}, JoinNumber = 222,
new JoinMetadata JoinSpan = 1
{ },
Description = "Specifies the screen index a participant should be pinned to", new JoinMetadata
JoinCapabilities = eJoinCapabilities.FromSIMPL, {
JoinType = eJoinType.Analog Description = "FB Indicates if layout 'Speaker' is available",
}); JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.DigitalSerial
#endregion });
[JoinName("LayoutStripIsAvailable")]
#region Serials public JoinDataComplete LayoutStripIsAvailable = new JoinDataComplete(
new JoinData
[JoinName("GetSetCurrentLayout")] {
public JoinDataComplete GetSetCurrentLayout = new JoinDataComplete( JoinNumber = 223,
new JoinData JoinSpan = 1
{ },
JoinNumber = 215, new JoinMetadata
JoinSpan = 1 {
}, Description = "FB Indicates if layout 'Strip' is available",
new JoinMetadata JoinCapabilities = eJoinCapabilities.ToSIMPL,
{ JoinType = eJoinType.DigitalSerial
Description = "Sets and reports the current layout. Use the LayoutXXXXIsAvailable signals to determine valid layouts", });
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial [JoinName("LayoutShareAllIsAvailable")]
}); public JoinDataComplete LayoutShareAllIsAvailable = new JoinDataComplete(
new JoinData
// TODO: #714 [ ] JoinMap >> GetSetSelfviewPipSize {
[JoinName("GetSetSelfviewPipSize")] JoinNumber = 224,
public JoinDataComplete GetSetSelfviewPipSize = new JoinDataComplete( JoinSpan = 1
new JoinData },
{ new JoinMetadata
JoinNumber = 230, {
JoinSpan = 1 Description = "FB Indicates if layout 'ShareAll' is available",
}, JoinCapabilities = eJoinCapabilities.ToSIMPL,
new JoinMetadata JoinType = eJoinType.DigitalSerial
{ });
Description = "Sets and reports the selfview pip size, (aka layout size).",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, // TODO: #714 [ ] JoinMap >> SelfivewPipSizeToggle
JoinType = eJoinType.DigitalSerial [JoinName("SelfviewPipSizeToggle")]
}); public JoinDataComplete SelfviewPipSizeToggle = new JoinDataComplete(
new JoinData
#endregion {
JoinNumber = 231,
public ZoomRoomJoinMap(uint joinStart) JoinSpan = 1
: base(joinStart, typeof(ZoomRoomJoinMap)) },
{ new JoinMetadata
} {
Description = "Toggles the selfview pip size, (aka layout size)",
public ZoomRoomJoinMap(uint joinStart, Type type) JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
: base(joinStart, type) JoinType = eJoinType.Digital
{ });
}
} //[JoinName("ParticipantAudioMuteToggleStart")]
//public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete(
// new JoinData
// {
// JoinNumber = 500,
// JoinSpan = 100
// },
// new JoinMetadata
// {
// Description = "Toggles the participant's audio mute status",
// JoinCapabilities = eJoinCapabilities.ToSIMPL,
// JoinType = eJoinType.Digital
// });
//[JoinName("ParticipantVideoMuteToggleStart")]
//public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete(
// new JoinData
// {
// JoinNumber = 800,
// JoinSpan = 100
// },
// new JoinMetadata
// {
// Description = "Toggles the participant's video mute status",
// JoinCapabilities = eJoinCapabilities.ToSIMPL,
// JoinType = eJoinType.Digital
// });
//[JoinName("ParticipantPinToggleStart")]
//public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete(
// new JoinData
// {
// JoinNumber = 1100,
// JoinSpan = 100
// },
// new JoinMetadata
// {
// Description = "Toggles the participant's pin status",
// JoinCapabilities = eJoinCapabilities.ToSIMPL,
// JoinType = eJoinType.Digital
// });
#endregion
#region Analog
[JoinName("NumberOfScreens")]
public JoinDataComplete NumberOfScreens = new JoinDataComplete(
new JoinData
{
JoinNumber = 11,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the number of screens connected",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("ScreenIndexToPinUserTo")]
public JoinDataComplete ScreenIndexToPinUserTo = new JoinDataComplete(
new JoinData
{
JoinNumber = 11,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Specifies the screen index a participant should be pinned to",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
#endregion
#region Serials
// TODO [ ] Issue #868
[JoinName("SubmitPassword")]
public JoinDataComplete SubmitPassword = new JoinDataComplete(
new JoinData
{
JoinNumber = 6,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Submit password text",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
// TODO [ ] Issue #868
[JoinName("PasswordPromptMessage")]
public JoinDataComplete PasswordPromptMessage = new JoinDataComplete(
new JoinData
{
JoinNumber = 6,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Password prompt message",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
// TODO [ ] Issue #868
[JoinName("MeetingInfoId")]
public JoinDataComplete MeetingInfoId = new JoinDataComplete(
new JoinData
{
JoinNumber = 11,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Meeting info ID text feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
// TODO [ ] Issue #868
[JoinName("MeetingInfoHostt")]
public JoinDataComplete MeetingInfoHost = new JoinDataComplete(
new JoinData
{
JoinNumber = 12,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Meeting info Host text feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
// TODO [ ] Issue #868
[JoinName("MeetingInfoPassword")]
public JoinDataComplete MeetingInfoPassword = new JoinDataComplete(
new JoinData
{
JoinNumber = 13,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Meeting info Password text feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("GetSetCurrentLayout")]
public JoinDataComplete GetSetCurrentLayout = new JoinDataComplete(
new JoinData
{
JoinNumber = 215,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Sets and reports the current layout. Use the LayoutXXXXIsAvailable signals to determine valid layouts",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
// TODO: #714 [ ] JoinMap >> GetSetSelfviewPipSize
[JoinName("GetSetSelfviewPipSize")]
public JoinDataComplete GetSetSelfviewPipSize = new JoinDataComplete(
new JoinData
{
JoinNumber = 230,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Sets and reports the selfview pip size, (aka layout size).",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.DigitalSerial
});
#endregion
public ZoomRoomJoinMap(uint joinStart)
: base(joinStart, typeof(ZoomRoomJoinMap))
{
}
public ZoomRoomJoinMap(uint joinStart, Type type)
: base(joinStart, type)
{
}
}
} }

View file

@ -2,30 +2,40 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
public class ZoomRoomPropertiesConfig public class ZoomRoomPropertiesConfig
{ {
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } [JsonProperty("communicationMonitorProperties")]
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
public bool DisablePhonebookAutoDownload { get; set; }
public bool SupportsCameraAutoMode { get; set; } [JsonProperty("disablePhonebookAutoDownload")]
public bool DisablePhonebookAutoDownload { get; set; }
[JsonProperty("supportsCameraAutoMode")]
public bool SupportsCameraAutoMode { get; set; }
[JsonProperty("supportsCameraOff")]
public bool SupportsCameraOff { get; set; } public bool SupportsCameraOff { get; set; }
//if true, the layouts will be set automatically when sharing starts/ends or a call is joined //if true, the layouts will be set automatically when sharing starts/ends or a call is joined
[JsonProperty("autoDefaultLayouts")]
public bool AutoDefaultLayouts { get; set; } public bool AutoDefaultLayouts { get; set; }
/* This layout will be selected when Sharing starts (either from Far end or locally)*/ /* This layout will be selected when Sharing starts (either from Far end or locally)*/
[JsonProperty("defaultSharingLayout")]
public string DefaultSharingLayout { get; set; } public string DefaultSharingLayout { get; set; }
//This layout will be selected when a call is connected and no content is being shared //This layout will be selected when a call is connected and no content is being shared
public string DefaultCallLayout { get; set; } [JsonProperty("defaultCallLayout")]
public string DefaultCallLayout { get; set; }
[JsonProperty("minutesBeforeMeetingStart")]
public int MinutesBeforeMeetingStart { get; set; } public int MinutesBeforeMeetingStart { get; set; }
} }
} }

View file

@ -1,3 +1,3 @@
<packages> <packages>
<package id="PepperDashCore" version="1.1.0" targetFramework="net35" allowedVersions="[1.0,2.0)"/> <package id="PepperDashCore" version="1.1.1-rc-247" targetFramework="net35" allowedVersions="[1.0,2.0)"/>
</packages> </packages>