Compare commits

...

62 Commits

Author SHA1 Message Date
Trevor Payne
d302a1b06b fix: merge in changes from issue #983
fix: DeviceInfo Null Check

Change IConvertiblePreset to abstract class ConvertiblePreset
2022-08-18 16:34:48 -05:00
Trevor Payne
780ec0aa4b fix: Check for local version 2022-08-17 13:22:48 -05:00
Trevor Payne
c2deaf9534 merge: feature/VideoCodec-Phonebook-Clear 2022-08-17 13:18:25 -05:00
Trevor Payne
cf3563d6b6 Merge branch 'feature/VideoCodec-Phonebook-Clear' into feature/explicit-essentials-version-check 2022-08-17 13:17:15 -05:00
Trevor Payne
e45643e9ab feat: add PluginDevelopmentDeviceFactory and associated Interfaces
feat: add method to Global to check against list of development versions
2022-08-17 13:01:21 -05:00
Trevor Payne
03a640d3d4 fix: Joinmap Index overwriting - adjusted 2022-08-12 16:18:58 -05:00
Trevor Payne
96cc263dbe feat: Resolves #982 2022-08-12 16:08:00 -05:00
Trevor Payne
9860e5f498 feat: Add method to clear selected phonebook entry 2022-08-12 15:58:19 -05:00
Andrew Welker
7298b9b767 Merge pull request #977 from PepperDash/hotfix/fix-lightingScene-scene-select-index
Hotfix/fix lighting scene scene select index
2022-08-08 15:49:19 -06:00
Andrew Welker
5a8914a33f Merge branch 'development' into hotfix/fix-lightingScene-scene-select-index 2022-08-08 13:34:27 -06:00
Jason DeVito
008c82edb9 fix: updated lighting and display base; fix: lightingBase scene recall link to api index out of range exception 2022-08-08 13:54:17 -05:00
Neil Dorin
3033322212 Merge pull request #973 from PepperDash/hotfix/multiple-display-routing-support
Fix interface type check for routing
2022-08-01 12:34:16 -06:00
Neil Dorin
5b350c7a0c Updates interface type for other condition 2022-08-01 12:19:43 -06:00
Neil Dorin
afd2198eef Uses a less specific interface type for routing 2022-08-01 12:19:28 -06:00
Trevor Payne
dccab58a28 Merge pull request #969 from PepperDash/bugfix/CrestronDatastor-Errors
Bugfix/crestron datastor errors
2022-07-19 09:54:53 -05:00
Andrew Welker
19d29a03c8 Merge branch 'development' into bugfix/CrestronDatastor-Errors 2022-07-19 08:33:47 -06:00
Andrew Welker
41bc6a9cd4 Merge pull request #967 from PepperDash/feature/VideoCodec-Improvements
Feature/video codec improvements
2022-07-19 08:33:30 -06:00
Trevor Payne
051d50e8c9 Merge branch 'bugfix/CrestronDatastor-Errors' of https://github.com/PepperDash/Essentials into bugfix/CrestronDatastor-Errors 2022-07-18 15:10:12 -05:00
Trevor Payne
16af75ae0d fix: updated erroneous console responses for Secrets Providers
refactor: updated method by which the Factories assess secret objects

refactor: updated 'SecretsManager' console responses

feat: added 'secretproviderlist' console command

feat: added 'secretproviderinfo' console command

feat: added 'CrestronGlobalSecretsProvider'

feat: Added 'Description' property to 'ISecretProvider'

feat: added 'TestSecret' method to 'ISecretProvider'

docs: added xml comments to 'ISecretProvider'

docs: added xml comments to 'ISecret'

refactor: cleaned up crestron default secrets provider classes

refactor: moved 'CrestronSecret' to its own class file

refactor: overhauled all secrets-related console commands

resolves #968
2022-07-18 15:07:19 -05:00
Trevor Payne
4037fad26b fix: updated erroneous console responses for Secrets Providers
refactor: updated method by which the Factories assess secret objects

refactor: updated 'SecretsManager' console responses

feat: added 'secretproviderlist' console command

feat: added 'secretproviderinfo' console command

feat: added 'CrestronGlobalSecretsProvider'

feat: Added 'Description' property to 'ISecretProvider'

feat: added 'TestSecret' method to 'ISecretProvider'

docs: added xml comments to 'ISecretProvider'

docs: added xml comments to 'ISecret'

refactor: cleaned up crestron default secrets provider classes

refactor: moved 'CrestronSecret' to its own class file

refactor: overhauled all secrets-related console commands
2022-07-18 15:05:08 -05:00
Trevor Payne
5a4cc2fd39 fix:console commands for Secrets Management Modified 2022-07-15 17:40:48 -05:00
Trevor Payne
04e8508c0c fix: requested changes for PR #967 2022-07-15 11:38:19 -05:00
Trevor Payne
cbab051c11 Fixed Merge Issue
Adjusts #966
2022-07-12 15:53:59 -05:00
Trevor Payne
9c8bb66c5e [Fix] - Updated IHasCodecLayoutsAvailable setters
[Adjusts] #966
2022-07-12 15:48:53 -05:00
Trevor Payne
96ec2cbe49 [Fix] - Updated IHasCodecLayoutsAvailable setters
[Adjusts] #966
2022-07-12 15:38:48 -05:00
Trevor Payne
9ecaec5584 [fix] slight change to move CodecCommandWithLabel into the VideoCodec namespace and modify the IHasCodecLayoutsAvailable interface to utilize this class
Modifies #966
2022-07-12 15:02:22 -05:00
Trevor Payne
b505ad467b [feature] added IHasCodecLayoutsAvailable interface and associated bridge linking methods
Modifies #966
2022-07-12 12:34:28 -05:00
Trevor Payne
d8ac302f1c [feature] - Create and Implement IConvertiblePreset within the VideoCodec and the VideoCodec.Cisco namespaces
RESOLVES #966
2022-07-11 17:30:51 -05:00
Neil Dorin
c3818b8bf2 Merge pull request #964 from PepperDash/feature/handle-prs
Feature/handle prs
2022-06-22 09:55:55 -06:00
Neil Dorin
05dadbe8ee Merge pull request #963 from PepperDash/hotfix/typo-in-RoutingPort-constructor
Hotfix/typo in routing port constructor
2022-06-22 09:54:43 -06:00
Neil Dorin
c39fd231bf Merge pull request #914 from Willis1776/bugfix/routingPort-typo-isInternal-Constructor
Typo in RoutingPort Constructor - isInternal
2022-06-22 09:38:30 -06:00
Neil Dorin
bbb31aea23 Merge pull request #959 from ciasia/bugfix/958-SubpageRefernceList-Get__OutputSig
GetStringOutputSig and GetUShortOutputSig return
2022-06-22 09:15:01 -06:00
Neil Dorin
0df587071d Merge branch 'main' into bugfix/routingPort-typo-isInternal-Constructor 2022-06-22 09:14:31 -06:00
Andrew Welker
4a405804c8 Merge pull request #960 from PepperDash/feature/iBasicVolumewFB-better-pull
Fix IBasicVolumeControls
2022-06-21 17:29:31 -05:00
jta
38c4a540a9 fix for IBasicVolumeWithFeedback
fix: for a change that split the interface but could break backwards compatibility #955
2022-06-21 18:05:23 -04:00
jta
4c9a470885 Fix IBasicVolumeControls
fix: revert a change that split the interface but could break backwards compatibility #955
2022-06-21 17:55:18 -04:00
Andrew Welker
be5158d29e Merge pull request #947 from PepperDash/feature/pdu-interface-joinmap
Added new Interfaces and JoinMap for PDUs
2022-06-21 15:40:54 -05:00
Andrew Welker
8ce390d650 Merge branch 'development' into feature/pdu-interface-joinmap 2022-06-21 13:42:17 -05:00
Neil Dorin
05066dc1ea Merge pull request #953 from PepperDash/hotfix/c2nio-factory-reference-update
Hotfix/c2nio factory reference update
2022-06-21 12:27:04 -06:00
Andrew Welker
70a78b540d Merge branch 'development' into feature/pdu-interface-joinmap 2022-06-21 13:12:50 -05:00
Andrew Welker
5e22ca9c59 Merge branch 'development' into hotfix/c2nio-factory-reference-update 2022-06-21 13:12:02 -05:00
Andrew Welker
5131e73567 Merge pull request #944 from PepperDash/hotfix/zoom-recording-prompt
Hotfix/zoom recording prompt
2022-06-21 13:11:45 -05:00
Neil Dorin
e02c267988 Merge branch 'development' into hotfix/zoom-recording-prompt 2022-06-21 11:47:33 -06:00
Rodney Driscoll
794ba7e6dd GetStringOutputSig and GetUShortOutputSig return 2022-06-17 09:38:16 +10:00
Neil Dorin
cd4f2d5edd Merge pull request #952 from PepperDash/hotfix/c2nio-factory-reference-update
fix: corrects issue #951, c2nio incorrect factory reference
2022-06-08 14:29:43 -06:00
Jason DeVito
59b18d713b fix: corrects issue #951, c2nio incorrect factory reference 2022-06-08 15:12:32 -05:00
Trevor Payne
1cc37b7521 feature:Converted PduOutlets Dictionary to ReadOnlyDictionary
feature:Removed redundant OutletCount property
2022-06-02 11:17:54 -05:00
Trevor Payne
86dfc395ec Rename IHasPowerReboot to IHasPowerCycle
Update naming scheme to Cycle from Reboot
2022-05-31 17:48:18 -05:00
Trevor Payne
05f3a7eb2c UpdateJoinmap Names 2022-05-31 17:46:13 -05:00
Trevor Payne
20beeb076a add new interfaces for implementing PDUs
added basic join map
2022-05-31 17:19:56 -05:00
Neil Dorin
a7db15d9fd Merge pull request #943 from PepperDash/hotfix/zoom-recording-prompt
Hotfix/zoom recording prompt
2022-05-18 17:14:19 -06:00
Neil Dorin
b8442e7048 feat(essentials): Format update for command 2022-05-18 16:33:21 -06:00
Neil Dorin
1e65c961c6 feat(essentials): Adds new interface capabilities
* ability to admit a participant from waiting room
* ability to acknowledge a meeting recording consent prompt
2022-05-17 15:36:00 -06:00
Neil Dorin
bdc4f0ae28 fix(essentials): updates recording property name 2022-05-17 13:20:53 -06:00
Neil Dorin
82ac34d3b6 fix(essentials): Updates Status.Call subscription mechanism to persist properly
Makes sure all subscriptions are un and resubscribed whenever Status.Call is constructed
2022-05-17 11:26:19 -06:00
Neil Dorin
23555e5174 Merge branch 'main' into hotfix/zoom-osd-device 2022-05-16 14:20:38 -06:00
Neil Dorin
7c892b4f71 Merge pull request #936 from PepperDash/hotfix/zoomroom-duplicate-passwordRequired-eventhandlers
fix: removed duplicate PasswordRequired event handler from LinkZoomRo…
2022-04-26 14:50:40 -06:00
Jason DeVito
309605ee38 fix: updated packages.config to reference PepperDash Core 1.1.1, previously referencing RC build 2022-03-29 16:04:14 -05:00
Jason DeVito
e2b8e356ff fix: Updated ZoomRoom constructor to build HdmiOutput1,2,3 2022-03-29 16:03:46 -05:00
Jason DeVito
832102f4bb feat: updated ExecuteSwitch to turn the display power on if _PowerIsOn is false 2022-03-29 16:02:59 -05:00
Neil Dorin
b23b7cb813 fix(essentials): #927 moves SetUpRouting() to constructor 2022-03-29 12:49:49 -06:00
Michael Willis
5f668c7173 Typo in RoutingPort Constructor - isInternal 2022-03-08 09:42:53 -07:00
39 changed files with 4428 additions and 3671 deletions

View File

@@ -708,11 +708,12 @@ namespace PepperDash.Essentials
IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice as IRoutingSinkNoSwitching;
dest = DefaultAudioDevice as IRoutingSink;
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
dest = DefaultDisplay;
else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
if (dest == null)
{

View File

@@ -0,0 +1,60 @@
using System;
namespace PepperDash.Essentials.Core.Bridges
{
public class PduJoinMapBase : JoinMapBaseAdvanced
{
[JoinName("Name")]
public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("Online")]
public JoinDataComplete Online = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital });
[JoinName("OutletCount")]
public JoinDataComplete OutletCount = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "Number of COntrolled Outlets", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog });
[JoinName("OutletName")]
public JoinDataComplete OutletName = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata { Description = "Outlet Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("OutletEnabled")]
public JoinDataComplete OutletEnabled = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata { Description = "Outlet Enabled", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital });
[JoinName("OutletPowerCycle")]
public JoinDataComplete OutletPowerCycle = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata { Description = "Outlet Power Cycle", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("OutletPowerOn")]
public JoinDataComplete OutletPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 },
new JoinMetadata { Description = "Outlet Power On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("OutletPowerOff")]
public JoinDataComplete OutletPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 },
new JoinMetadata { Description = "Outlet Power Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
/// <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 PduJoinMapBase(uint joinStart)
:base(joinStart, typeof(PduJoinMapBase))
{
}
/// <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>
public PduJoinMapBase(uint joinStart, Type type)
: base(joinStart, type)
{
}
}
}

View File

@@ -1,35 +1,35 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Core.Config
{
public class DeviceConfig
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("uid")]
public int Uid { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("group")]
public string Group { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("properties")]
[JsonConverter(typeof(DevicePropertiesConverter))]
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Core.Config
{
public class DeviceConfig
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("uid")]
public int Uid { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("group")]
public string Group { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("properties")]
[JsonConverter(typeof(DevicePropertiesConverter))]
public JToken Properties { get; set; }
public DeviceConfig(DeviceConfig dc)
@@ -39,39 +39,42 @@ namespace PepperDash.Essentials.Core.Config
Name = dc.Name;
Group = dc.Group;
Type = dc.Type;
Properties = JToken.FromObject(dc.Properties);
Properties = JToken.Parse(dc.Properties.ToString());
//Properties = JToken.FromObject(dc.Properties);
}
public DeviceConfig() {}
}
/// <summary>
///
/// </summary>
public class DevicePropertiesConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(JToken);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return JToken.ReadFrom(reader);
}
public override bool CanWrite
{
get
{
return false;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException("SOD OFF HOSER");
}
}
}
/// <summary>
///
/// </summary>
public class DevicePropertiesConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(JToken);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return JToken.ReadFrom(reader);
}
public override bool CanWrite
{
get
{
return false;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException("SOD OFF HOSER");
}
}
}

View File

@@ -66,7 +66,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
#endregion
}
public class C2NIoControllerFactory : EssentialsDeviceFactory<C2nRthsController>
public class C2NIoControllerFactory : EssentialsDeviceFactory<C2NIoController>
{
public C2NIoControllerFactory()
{

View File

@@ -131,4 +131,15 @@ namespace PepperDash.Essentials.Core
/// </summary>
public string MinimumEssentialsFrameworkVersion { get; protected set; }
}
public abstract class EssentialsPluginDevelopmentDeviceFactory<T> : EssentialsDeviceFactory<T>, IPluginDevelopmentDeviceFactory where T : EssentialsDevice
{
/// <summary>
/// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33")
/// </summary>
public string MinimumEssentialsFrameworkVersion { get; protected set; }
public List<string> DevelopmentEssentialsFrameworkVersions { get; protected set; }
}
}

View File

@@ -9,8 +9,11 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// Defines minimal volume and mute control methods
/// </summary>
public interface IBasicVolumeControls : IHasVolumeControl, IHasMuteControl
public interface IBasicVolumeControls
{
void VolumeUp(bool pressRelease);
void VolumeDown(bool pressRelease);
void MuteToggle();
}
/// <summary>
@@ -52,8 +55,13 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// Adds feedback and direct volume level set to IBasicVolumeControls
/// </summary>
public interface IBasicVolumeWithFeedback : IBasicVolumeControls, IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback
public interface IBasicVolumeWithFeedback : IBasicVolumeControls
{
BoolFeedback MuteFeedback { get; }
void MuteOn();
void MuteOff();
void SetVolume(ushort level);
IntFeedback VolumeLevelFeedback { get; }
}
/// <summary>

View File

@@ -0,0 +1,35 @@
using System.Collections.Generic;
using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash_Essentials_Core.Devices
{
/// <summary>
/// Interface for any device that is able to control it'spower and has a configurable reboot time
/// </summary>
public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback
{
/// <summary>
/// Delay between power off and power on for reboot
/// </summary>
int PowerCycleTimeMs { get;}
/// <summary>
/// Reboot outlet
/// </summary>
void PowerCycle();
}
/// <summary>
/// Interface for any device that contains a collection of IHasPowerReboot Devices
/// </summary>
public interface IHasControlledPowerOutlets : IKeyName
{
/// <summary>
/// Collection of IPduOutlets
/// </summary>
ReadOnlyDictionary<int, IHasPowerCycle> PduOutlets { get; }
}
}

View File

@@ -59,7 +59,7 @@ namespace PepperDash.Essentials.Core.Devices
/// <summary>
/// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc)
/// </summary>
/// <param name="Config"></param>
/// <param name="config"></param>
protected virtual void CustomSetConfig(DeviceConfig config)
{
ConfigWriter.UpdateDeviceConfig(config);

View File

@@ -105,9 +105,6 @@ namespace PepperDash.Essentials.Core
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
EiscApiAdvanced bridge)
{
var inputNumber = 0;
var inputKeys = new List<string>();
var joinMap = new DisplayControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
@@ -124,133 +121,141 @@ namespace PepperDash.Essentials.Core
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(0, "Linking to Display: {0}", displayDevice.Name);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name;
var commMonitor = displayDevice as ICommunicationMonitor;
if (commMonitor != null)
{
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
}
var inputNumberFeedback = new IntFeedback(() => inputNumber);
// Two way feedbacks
var twoWayDisplay = displayDevice as TwoWayDisplayBase;
if (twoWayDisplay != null)
{
trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true);
twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.Console(0, "CurrentInputFeedback_OutputChange {0}", a.StringValue);
inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]);
}
// Power Off
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOff();
});
var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase;
if (twoWayDisplayDevice != null)
{
twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!a.BoolValue)
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
}
else
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
}
};
twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
}
// PowerOn
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOn();
});
for (int i = 0; i < displayDevice.InputPorts.Count; i++)
{
if (i < joinMap.InputNamesOffset.JoinSpan)
{
inputKeys.Add(displayDevice.InputPorts[i].Key);
var tempKey = inputKeys.ElementAt(i);
trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i),
() => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
Debug.Console(2, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}",
joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString());
trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString();
}
else
Debug.Console(0, displayDevice, Debug.ErrorLogLevel.Warning, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.",
displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count);
}
Debug.Console(2, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) =>
{
if (a == 0)
{
displayDevice.PowerOff();
inputNumber = 0;
}
else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber)
{
displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector);
inputNumber = a;
}
else if (a == 102)
{
displayDevice.PowerToggle();
}
if (twoWayDisplay != null)
inputNumberFeedback.FireUpdate();
});
var volumeDisplay = displayDevice as IBasicVolumeControls;
if (volumeDisplay == null) return;
trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, volumeDisplay.VolumeUp);
trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, volumeDisplay.VolumeDown);
trilist.SetSigTrueAction(joinMap.VolumeMute.JoinNumber, volumeDisplay.MuteToggle);
var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback;
if (volumeDisplayWithFeedback == null) return;
trilist.SetSigTrueAction(joinMap.VolumeMuteOn.JoinNumber, volumeDisplayWithFeedback.MuteOn);
trilist.SetSigTrueAction(joinMap.VolumeMuteOff.JoinNumber, volumeDisplayWithFeedback.MuteOff);
trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, volumeDisplayWithFeedback.SetVolume);
volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]);
LinkDisplayToApi(displayDevice, trilist, joinMap);
}
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap)
{
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Display: {0}", displayDevice.Name);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name;
var commMonitor = displayDevice as ICommunicationMonitor;
if (commMonitor != null)
{
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
}
var inputNumber = 0;
var inputKeys = new List<string>();
var inputNumberFeedback = new IntFeedback(() => inputNumber);
// Two way feedbacks
var twoWayDisplay = displayDevice as TwoWayDisplayBase;
if (twoWayDisplay != null)
{
trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true);
twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.Console(0, "CurrentInputFeedback_OutputChange {0}", a.StringValue);
inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]);
}
// Power Off
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOff();
});
var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase;
if (twoWayDisplayDevice != null)
{
twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!a.BoolValue)
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
}
else
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
}
};
twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
}
// PowerOn
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOn();
});
for (int i = 0; i < displayDevice.InputPorts.Count; i++)
{
if (i < joinMap.InputNamesOffset.JoinSpan)
{
inputKeys.Add(displayDevice.InputPorts[i].Key);
var tempKey = inputKeys.ElementAt(i);
trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i),
() => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
Debug.Console(2, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}",
joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString());
trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString();
}
else
Debug.Console(0, displayDevice, Debug.ErrorLogLevel.Warning, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.",
displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count);
}
Debug.Console(2, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) =>
{
if (a == 0)
{
displayDevice.PowerOff();
inputNumber = 0;
}
else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber)
{
displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector);
inputNumber = a;
}
else if (a == 102)
{
displayDevice.PowerToggle();
}
if (twoWayDisplay != null)
inputNumberFeedback.FireUpdate();
});
var volumeDisplay = displayDevice as IBasicVolumeControls;
if (volumeDisplay == null) return;
trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, volumeDisplay.VolumeUp);
trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, volumeDisplay.VolumeDown);
trilist.SetSigTrueAction(joinMap.VolumeMute.JoinNumber, volumeDisplay.MuteToggle);
var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback;
if (volumeDisplayWithFeedback == null) return;
trilist.SetSigTrueAction(joinMap.VolumeMuteOn.JoinNumber, volumeDisplayWithFeedback.MuteOn);
trilist.SetSigTrueAction(joinMap.VolumeMuteOff.JoinNumber, volumeDisplayWithFeedback.MuteOff);
trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, volumeDisplayWithFeedback.SetVolume);
volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]);
}
}
/// <summary>

View File

@@ -111,7 +111,12 @@ namespace PepperDash.Essentials.Core
public override void ExecuteSwitch(object selector)
{
Debug.Console(2, this, "ExecuteSwitch: {0}", selector);
Debug.Console(2, this, "ExecuteSwitch: {0}", selector);
if (!_PowerIsOn)
{
PowerOn();
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Globalization;
using Crestron.SimplSharp;
@@ -122,6 +123,38 @@ namespace PepperDash.Essentials.Core
AssemblyVersion = assemblyVersion;
}
public static bool IsRunningDevelopmentVersion(List<string> developmentVersions, string minimumVersion)
{
if (Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*").Groups[1].Value == "0")
{
Debug.Console(2, "Running Local Build. Bypassing Dependency Check.");
return true;
}
if (developmentVersions == null)
{
Debug.Console(0,
"Development Plugin does not specify a list of versions. Loading plugin may not work as expected. Checking Minumum version");
return IsRunningMinimumVersionOrHigher(minimumVersion);
}
Debug.Console(2, "Comparing running version '{0}' to minimum versions '{1}'", AssemblyVersion, developmentVersions);
var versionMatch = developmentVersions.FirstOrDefault(x => x == AssemblyVersion);
if (String.IsNullOrEmpty(versionMatch))
{
Debug.Console(0, "Essentials Build does not match any builds required for plugin load. Bypassing Plugin Load.");
return false;
}
Debug.Console(2, "Essentials Build {0} matches list of development builds", AssemblyVersion);
return IsRunningMinimumVersionOrHigher(minimumVersion);
}
/// <summary>
/// Checks to see if the running version meets or exceed the minimum specified version. For beta versions (0.xx.yy), will always return true.
/// </summary>

View File

@@ -70,50 +70,69 @@ namespace PepperDash.Essentials.Core.Lighting
}
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
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);
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.");
}
return LinkLightingToApi(lightingDevice, trilist, joinMap);
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap)
{
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
// GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
var sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var joinMap = new GenericLightingJoinMap(joinStart);
var index = sceneIndex;
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]);
trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
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, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
// GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
var sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index1 = sceneIndex;
trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex), () =>
{
var index = index1;
Debug.Console(2, this, "LightingDevice: sceneIndex: {0} index: {1} > inside action", index1, index);
lightingDevice.SelectScene(lightingDevice.LightingScenes[index]);
});
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)]);
trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + sceneIndex)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + sceneIndex)].BoolValue = true;
sceneIndex++;
}
return joinMap;
sceneIndex++;
}
trilist.OnlineStatusChange += (sender, args) =>
{
if (!args.DeviceOnLine) return;
sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
scene.IsActiveFeedback.FireUpdate();
sceneIndex++;
}
};
return joinMap;
}
}
public class LightingScene

View File

@@ -123,6 +123,7 @@
<Compile Include="Bridges\IBridge.cs" />
<Compile Include="Bridges\JoinMaps\AirMediaControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\AppleTvJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\PduJoinMapBase.cs" />
<Compile Include="Bridges\JoinMaps\C2nRthsControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\CameraControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\CenOdtOccupancySensorBaseJoinMap.cs" />
@@ -203,6 +204,7 @@
<Compile Include="Devices\IReconfigurableDevice.cs" />
<Compile Include="Devices\PC\InRoomPc.cs" />
<Compile Include="Devices\PC\Laptop.cs" />
<Compile Include="Devices\PduInterfaces.cs" />
<Compile Include="Devices\ReconfigurableDevice.cs" />
<Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" />
<Compile Include="DeviceTypeInterfaces\IPasswordPrompt.cs" />
@@ -336,7 +338,9 @@
<Compile Include="Feedbacks\BoolFeedbackPulseExtender.cs" />
<Compile Include="Routing\RoutingPortNames.cs" />
<Compile Include="Routing\TieLineConfig.cs" />
<Compile Include="Secrets\CrestronSecretsProvider.cs" />
<Compile Include="Secrets\CrestronGlobalSecretsProvider.cs" />
<Compile Include="Secrets\CrestronLocalSecretsProvider.cs" />
<Compile Include="Secrets\CrestronSecret.cs" />
<Compile Include="Secrets\Interfaces.cs" />
<Compile Include="Secrets\SecretsManager.cs" />
<Compile Include="Secrets\SecretsPropertiesConfig.cs" />

View File

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using PepperDash.Core;
@@ -15,5 +16,10 @@ namespace PepperDash.Essentials.Core
}
public interface IPluginDevelopmentDeviceFactory : IPluginDeviceFactory
{
List<string> DevelopmentEssentialsFrameworkVersions { get; }
}
}
}

View File

@@ -425,7 +425,11 @@ namespace PepperDash.Essentials
/// <param name="loadedAssembly"></param>
static void LoadCustomPlugin(IPluginDeviceFactory plugin, LoadedAssembly loadedAssembly)
{
var passed = Global.IsRunningMinimumVersionOrHigher(plugin.MinimumEssentialsFrameworkVersion);
var developmentPlugin = plugin as IPluginDevelopmentDeviceFactory;
var passed = developmentPlugin != null ? Global.IsRunningDevelopmentVersion
(developmentPlugin.DevelopmentEssentialsFrameworkVersions, developmentPlugin.MinimumEssentialsFrameworkVersion)
: Global.IsRunningMinimumVersionOrHigher(plugin.MinimumEssentialsFrameworkVersion);
if (!passed)
{

View File

@@ -25,7 +25,7 @@ namespace PepperDash.Essentials.Core
Type = type;
ConnectionType = connType;
Selector = selector;
IsInternal = IsInternal;
IsInternal = isInternal;
}
}

View File

@@ -0,0 +1,102 @@
using System;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronDataStore;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public class CrestronGlobalSecretsProvider : ISecretProvider
{
public string Key { get; set; }
//Added for reference
public string Description { get; private set; }
public CrestronGlobalSecretsProvider(string key)
{
Key = key;
Description = String.Format("Default secret provider serving all local applications");
}
static CrestronGlobalSecretsProvider()
{
//Added for future encrypted reference
var secureSupported = CrestronSecureStorage.Supported;
CrestronDataStoreStatic.InitCrestronDataStore();
if (secureSupported)
{
//doThingsFuture
}
}
/// <summary>
/// Set secret for item in the CrestronSecretsProvider
/// </summary>
/// <param name="key">Secret Key</param>
/// <param name="value">Secret Value</param>
public bool SetSecret(string key, object value)
{
var secret = value as string;
CrestronDataStore.CDS_ERROR returnCode;
if (String.IsNullOrEmpty(secret))
{
returnCode = CrestronDataStoreStatic.clearGlobal(key);
if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
{
Debug.Console(0, this, "Successfully removed secret \"{0}\"", secret);
return true;
}
}
else
{
returnCode = CrestronDataStoreStatic.SetGlobalStringValue(key, secret);
if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
{
Debug.Console(0, this, "Successfully set secret \"{0}\"", secret);
return true;
}
}
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString());
return false;
}
/// <summary>
/// Retrieve secret for item in the CrestronSecretsProvider
/// </summary>
/// <param name="key">Secret Key</param>
/// <returns>ISecret Object containing key, provider, and value</returns>
public ISecret GetSecret(string key)
{
string mySecret;
var getErrorCode = CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret);
switch (getErrorCode)
{
case CrestronDataStore.CDS_ERROR.CDS_SUCCESS:
Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key);
return new CrestronSecret(key, mySecret, this);
default:
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}",
Key, key, getErrorCode.ToString());
return null;
}
}
/// <summary>
/// Determine if a secret is present within the provider without retrieving it
/// </summary>
/// <param name="key">Secret Key</param>
/// <returns>bool if present</returns>
public bool TestSecret(string key)
{
string mySecret;
return CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS;
}
}
}

View File

@@ -1,97 +1,103 @@
using System;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronDataStore;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public class CrestronSecretsProvider : ISecretProvider
{
public string Key { get; set; }
//Added for reference
private static readonly bool SecureSupported;
public CrestronSecretsProvider(string key)
{
Key = key;
}
static CrestronSecretsProvider()
{
//Added for future encrypted reference
SecureSupported = CrestronSecureStorage.Supported;
CrestronDataStoreStatic.InitCrestronDataStore();
if (SecureSupported)
{
//doThingsFuture
}
}
/// <summary>
/// Set secret for item in the CrestronSecretsProvider
/// </summary>
/// <param name="key">Secret Key</param>
/// <param name="value">Secret Value</param>
public bool SetSecret(string key, object value)
{
var secret = value as string;
if (String.IsNullOrEmpty(secret))
{
Debug.Console(2, this, "Unable to set secret for {0}:{1} - value is empty.", Key, key);
return false;
}
var setErrorCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret);
switch (setErrorCode)
{
case CrestronDataStore.CDS_ERROR.CDS_SUCCESS:
Debug.Console(1, this,"Secret Successfully Set for {0}:{1}", Key, key);
return true;
default:
Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, setErrorCode.ToString());
return false;
}
}
/// <summary>
/// Retrieve secret for item in the CrestronSecretsProvider
/// </summary>
/// <param name="key">Secret Key</param>
/// <returns>ISecret Object containing key, provider, and value</returns>
public ISecret GetSecret(string key)
{
string mySecret;
var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret);
switch (getErrorCode)
{
case CrestronDataStore.CDS_ERROR.CDS_SUCCESS:
Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key);
return new CrestronSecret(key, mySecret, this);
default:
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}",
Key, key, getErrorCode.ToString());
return null;
}
}
}
/// <summary>
/// Special container class for CrestronSecret provider
/// </summary>
public class CrestronSecret : ISecret
{
public ISecretProvider Provider { get; private set; }
public string Key { get; private set; }
public object Value { get; private set; }
public CrestronSecret(string key, string value, ISecretProvider provider)
{
Key = key;
Value = value;
Provider = provider;
}
}
using System;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronDataStore;
using PepperDash.Core;
using Crestron.SimplSharpPro;
namespace PepperDash.Essentials.Core
{
public class CrestronLocalSecretsProvider : ISecretProvider
{
public string Key { get; set; }
//Added for reference
public string Description { get; private set; }
public CrestronLocalSecretsProvider(string key)
{
Key = key;
Description = String.Format("Default secret provider serving Essentials Application {0}", InitialParametersClass.ApplicationNumber);
}
static CrestronLocalSecretsProvider()
{
//Added for future encrypted reference
var secureSupported = CrestronSecureStorage.Supported;
CrestronDataStoreStatic.InitCrestronDataStore();
if (secureSupported)
{
//doThingsFuture
}
}
/// <summary>
/// Set secret for item in the CrestronSecretsProvider
/// </summary>
/// <param name="key">Secret Key</param>
/// <param name="value">Secret Value</param>
public bool SetSecret(string key, object value)
{
var secret = value as string;
CrestronDataStore.CDS_ERROR returnCode;
if (String.IsNullOrEmpty(secret))
{
returnCode = CrestronDataStoreStatic.clearLocal(key);
if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
{
Debug.Console(0, this, "Successfully removed secret \"{0}\"", secret);
return true;
}
}
else
{
returnCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret);
if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
{
Debug.Console(0, this, "Successfully set secret \"{0}\"", secret);
return true;
}
}
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString());
return false;
}
/// <summary>
/// Retrieve secret for item in the CrestronSecretsProvider
/// </summary>
/// <param name="key">Secret Key</param>
/// <returns>ISecret Object containing key, provider, and value</returns>
public ISecret GetSecret(string key)
{
string mySecret;
var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret);
switch (getErrorCode)
{
case CrestronDataStore.CDS_ERROR.CDS_SUCCESS:
Debug.Console(2, this, "Secret Successfully retrieved for {0}:{1}", Key, key);
return new CrestronSecret(key, mySecret, this);
default:
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Unable to retrieve secret for {0}:{1} - {2}",
Key, key, getErrorCode.ToString());
return null;
}
}
/// <summary>
/// Determine if a secret is present within the provider without retrieving it
/// </summary>
/// <param name="key">Secret Key</param>
/// <returns>bool if present</returns>
public bool TestSecret(string key)
{
string mySecret;
return CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS;
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Special container class for CrestronSecret provider
/// </summary>
public class CrestronSecret : ISecret
{
public ISecretProvider Provider { get; private set; }
public string Key { get; private set; }
public object Value { get; private set; }
public CrestronSecret(string key, string value, ISecretProvider provider)
{
Key = key;
Value = value;
Provider = provider;
}
}
}

View File

@@ -7,9 +7,32 @@ namespace PepperDash.Essentials.Core
/// </summary>
public interface ISecretProvider : IKeyed
{
/// <summary>
/// Set secret value for provider by key
/// </summary>
/// <param name="key">key of secret to set</param>
/// <param name="value">value to set secret to</param>
/// <returns></returns>
bool SetSecret(string key, object value);
/// <summary>
/// Return object containing secret from provider
/// </summary>
/// <param name="key">key of secret to retrieve</param>
/// <returns></returns>
ISecret GetSecret(string key);
/// <summary>
/// Verifies presence of secret
/// </summary>
/// <param name="key">key of secret to chek</param>
/// <returns></returns>
bool TestSecret(string key);
/// <summary>
/// Description of the secrets provider
/// </summary>
string Description { get; }
}
/// <summary>
@@ -17,8 +40,19 @@ namespace PepperDash.Essentials.Core
/// </summary>
public interface ISecret
{
/// <summary>
/// Instance of ISecretProvider that the secret belongs to
/// </summary>
ISecretProvider Provider { get; }
/// <summary>
/// Key of the secret in the provider
/// </summary>
string Key { get; }
/// <summary>
/// Value of the secret
/// </summary>
object Value { get; }
}
}

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public static class SecretsManager
@@ -16,18 +16,28 @@ namespace PepperDash.Essentials.Core
public static void Initialize()
{
AddSecretProvider("default", new CrestronSecretsProvider("default"));
AddSecretProvider("default", new CrestronLocalSecretsProvider("default"));
AddSecretProvider("CrestronGlobalSecrets", new CrestronGlobalSecretsProvider("CrestronGlobalSecrets"));
CrestronConsole.AddNewConsoleCommand(SetSecretProcess, "setsecret",
"Adds secrets to secret provider",
"Adds secret to secrets provider",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(UpdateSecretProcess, "updatesecret",
"Updates secrets in secret provider",
"Updates secret in secrets provider",
ConsoleAccessLevelEnum.AccessAdministrator);
CrestronConsole.AddNewConsoleCommand(DeleteSecretProcess, "deletesecret",
"Deletes secrets in secret provider",
"Deletes secret from secrest provider",
ConsoleAccessLevelEnum.AccessAdministrator);
CrestronConsole.AddNewConsoleCommand(ListProviders, "secretproviderlist",
"Return list of all valid secrets providers",
ConsoleAccessLevelEnum.AccessAdministrator);
CrestronConsole.AddNewConsoleCommand(GetProviderInfo, "secretproviderinfo",
"Return data about secrets provider",
ConsoleAccessLevelEnum.AccessAdministrator);
}
@@ -54,6 +64,79 @@ namespace PepperDash.Essentials.Core
return secret;
}
public static void GetProviderInfo(string cmd)
{
string response;
var args = cmd.Split(' ');
if (cmd.Length == 0 || (args.Length == 1 && args[0] == "?"))
{
response = "Returns data about secrets provider. Format 'secretproviderinfo <provider>'";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length == 1)
{
var provider = GetSecretProviderByKey(args[0]);
if (provider == null)
{
response = "Invalid secrets provider key";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
response = String.Format("{0} : {1}", provider.Key, provider.Description);
CrestronConsole.ConsoleCommandResponse(response);
return;
}
response = "Improper number of arguments";
CrestronConsole.ConsoleCommandResponse(response);
}
/// <summary>
/// Console Command that returns all valid secrets in the essentials program.
/// </summary>
/// <param name="cmd"></param>
public static void ListProviders(string cmd)
{
var response = String.Empty;
var args = cmd.Split(' ');
if (cmd.Length == 0)
{
if (Secrets != null && Secrets.Count > 0)
{
response = Secrets.Aggregate(response,
(current, secretProvider) => current + (secretProvider.Key + "\n\r"));
}
else
{
response = "No Secrets Providers Available";
}
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length == 1 && args[0] == "?")
{
response = "Reports all valid and preset Secret providers";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
response = "Improper number of arguments";
CrestronConsole.ConsoleCommandResponse(response);
}
/// <summary>
/// Add secret provider to secrets dictionary
/// </summary>
@@ -100,14 +183,14 @@ namespace PepperDash.Essentials.Core
if (args.Length == 0)
{
//some Instructional Text
response = "Adds secrets to secret provider. Format 'setsecret <provider> <secretKey> <secret>";
response = "Adds secrets to secret provider. Format 'setsecret <provider> <secretKey> <secret>'";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length == 1 && args[0] == "?")
{
response = "Adds secrets to secret provider. Format 'setsecret <provider> <secretKey> <secret>";
response = "Adds secrets to secret provider. Format 'setsecret <provider> <secretKey> <secret>'";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
@@ -134,23 +217,7 @@ namespace PepperDash.Essentials.Core
var key = args[1];
var secret = args[2];
if (provider.GetSecret(key) == null)
{
response = provider.SetSecret(key, secret)
? String.Format(
"Secret successfully set for {0}:{1}",
provider.Key, key)
: String.Format(
"Unable to set secret for {0}:{1}",
provider.Key, key);
CrestronConsole.ConsoleCommandResponse(response);
return;
}
response =
String.Format(
"Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it");
CrestronConsole.ConsoleCommandResponse(response);
CrestronConsole.ConsoleCommandResponse(SetSecret(provider, key, secret));
}
private static void UpdateSecretProcess(string cmd)
@@ -161,7 +228,7 @@ namespace PepperDash.Essentials.Core
if (args.Length == 0)
{
//some Instructional Text
response = "Updates secrets in secret provider. Format 'updatesecret <provider> <secretKey> <secret>";
response = "Updates secrets in secret provider. Format 'updatesecret <provider> <secretKey> <secret>'";
CrestronConsole.ConsoleCommandResponse(response);
return;
@@ -169,7 +236,7 @@ namespace PepperDash.Essentials.Core
if (args.Length == 1 && args[0] == "?")
{
response = "Updates secrets in secret provider. Format 'updatesecret <provider> <secretKey> <secret>";
response = "Updates secrets in secret provider. Format 'updatesecret <provider> <secretKey> <secret>'";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
@@ -198,23 +265,49 @@ namespace PepperDash.Essentials.Core
var key = args[1];
var secret = args[2];
if (provider.GetSecret(key) != null)
{
response = provider.SetSecret(key, secret)
? String.Format(
"Secret successfully set for {0}:{1}",
provider.Key, key)
: String.Format(
"Unable to set secret for {0}:{1}",
provider.Key, key);
CrestronConsole.ConsoleCommandResponse(response);
return;
}
CrestronConsole.ConsoleCommandResponse(UpdateSecret(provider, key, secret));
}
private static string UpdateSecret(ISecretProvider provider, string key, string secret)
{
var secretPresent = provider.TestSecret(key);
Debug.Console(2, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key);
if (!secretPresent)
return
String.Format(
"Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to modify it");
var response = provider.SetSecret(key, secret)
? String.Format(
"Secret successfully set for {0}:{1}",
provider.Key, key)
: String.Format(
"Unable to set secret for {0}:{1}",
provider.Key, key);
return response;
}
private static string SetSecret(ISecretProvider provider, string key, string secret)
{
var secretPresent = provider.TestSecret(key);
Debug.Console(2, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key);
if (secretPresent)
return
String.Format(
"Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it");
var response = provider.SetSecret(key, secret)
? String.Format(
"Secret successfully set for {0}:{1}",
provider.Key, key)
: String.Format(
"Unable to set secret for {0}:{1}",
provider.Key, key);
return response;
response =
String.Format(
"Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to create a new secret");
CrestronConsole.ConsoleCommandResponse(response);
}
private static void DeleteSecretProcess(string cmd)
@@ -225,14 +318,14 @@ namespace PepperDash.Essentials.Core
if (args.Length == 0)
{
//some Instructional Text
response = "Deletes secrets in secret provider. Format 'deletesecret <provider> <secretKey>";
response = "Deletes secrets in secret provider. Format 'deletesecret <provider> <secretKey>'";
CrestronConsole.ConsoleCommandResponse(response);
return;
}
if (args.Length == 1 && args[0] == "?")
{
response = "Deletes secrets in secret provider. Format 'deletesecret <provider> <secretKey>";
response = "Deletes secrets in secret provider. Format 'deletesecret <provider> <secretKey>'";
CrestronConsole.ConsoleCommandResponse(response);
return;
}

View File

@@ -144,7 +144,7 @@ namespace PepperDash.Essentials.Core
public UShortOutputSig GetUShortOutputSig(uint index, uint sigNum)
{
if (sigNum > UShortIncrement) return null;
return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetBoolFeedbackSigName(index, sigNum)));
return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetUShortOutputSigName(index, sigNum)));
}
/// <summary>
@@ -159,7 +159,7 @@ namespace PepperDash.Essentials.Core
public StringOutputSig GetStringOutputSig(uint index, uint sigNum)
{
if (sigNum > StringIncrement) return null;
return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetBoolFeedbackSigName(index, sigNum)));
return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetStringOutputSigName(index, sigNum)));
}
/// <summary>

View File

@@ -108,6 +108,7 @@
<Compile Include="Codec\eCodecCallStatus.cs" />
<Compile Include="Codec\eMeetingPrivacy.cs" />
<Compile Include="Codec\iCodecAudio.cs" />
<Compile Include="VideoCodec\ConvertiblePreset.cs" />
<Compile Include="Codec\IHasCallHold.cs" />
<Compile Include="Codec\IHasDoNotDisturb.cs" />
<Compile Include="Codec\IHasExternalSourceSwitching.cs" />

View File

@@ -1023,18 +1023,21 @@ ConnectorID: {2}"
if (tempPresets.Count > 0)
{
// Create temporary list to store the existing items from the CiscoCodecStatus.RoomPreset collection
List<CiscoCodecStatus.RoomPreset> existingRoomPresets = new List<CiscoCodecStatus.RoomPreset>();
var existingRoomPresets = new List<CiscoCodecStatus.RoomPreset>();
// Add the existing items to the temporary list
existingRoomPresets.AddRange(CodecStatus.Status.RoomPreset);
// Populate the CodecStatus object (this will append new values to the RoomPreset collection
JsonConvert.PopulateObject(response, CodecStatus);
JObject jResponse = JObject.Parse(response);
var jResponse = JObject.Parse(response);
IList<JToken> roomPresets = jResponse["Status"]["RoomPreset"].Children().ToList();
// Iterate the new items in this response agains the temporary list. Overwrite any existing items and add new ones.
foreach (var preset in tempPresets)
foreach (var camPreset in tempPresets)
{
var preset = camPreset as CiscoCodecStatus.RoomPreset;
if (preset == null) continue;
// First fine the existing preset that matches the id
var existingPreset = existingRoomPresets.FirstOrDefault(p => p.id.Equals(preset.id));
if (existingPreset != null)
@@ -1068,7 +1071,7 @@ ConnectorID: {2}"
CodecStatus.Status.RoomPreset = existingRoomPresets;
// Generecise the list
NearEndPresets = RoomPresets.GetGenericPresets(CodecStatus.Status.RoomPreset);
NearEndPresets = existingRoomPresets.GetGenericPresets<CiscoCodecStatus.RoomPreset, CodecRoomPreset>();
var handler = CodecRoomPresetsListHasChanged;
if (handler != null)
@@ -2465,20 +2468,6 @@ ConnectorID: {2}"
}
/// <summary>
/// Represents a codec command that might need to have a friendly label applied for UI feedback purposes
/// </summary>
public class CodecCommandWithLabel
{
public string Command { get; set; }
public string Label { get; set; }
public CodecCommandWithLabel(string command, string label)
{
Command = command;
Label = label;
}
}
/// <summary>
/// Tracks the initial sycnronization state of the codec when making a connection

View File

@@ -1,14 +1,9 @@
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.Presets;
using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
@@ -33,39 +28,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public static class RoomPresets
{
/// <summary>
/// Converts Cisco RoomPresets to generic CameraPresets
/// Converts non-generic RoomPresets to generic CameraPresets
/// </summary>
/// <param name="presets"></param>
/// <returns></returns>
public static List<CodecRoomPreset> GetGenericPresets(List<CiscoCodecStatus.RoomPreset> presets)
public static List<TDestination> GetGenericPresets<TSource, TDestination>(this List<TSource> presets) where TSource : ConvertiblePreset where TDestination : PresetBase
{
var cameraPresets = new List<CodecRoomPreset>();
if (Debug.Level > 0)
{
Debug.Console(1, "Presets List:");
}
foreach (CiscoCodecStatus.RoomPreset preset in presets)
{
try
{
var cameraPreset = new CodecRoomPreset(UInt16.Parse(preset.id), preset.Description.Value, preset.Defined.BoolValue, true);
cameraPresets.Add(cameraPreset);
if (Debug.Level > 0)
{
Debug.Console(1, "Added Preset ID: {0}, Description: {1}, IsDefined: {2}, isDefinable: {3}", cameraPreset.ID, cameraPreset.Description, cameraPreset.Defined, cameraPreset.IsDefinable);
}
}
catch (Exception e)
{
Debug.Console(2, "Unable to convert preset: {0}. Error: {1}", preset.id, e);
}
}
return cameraPresets;
return
presets.Select(preset => preset.ConvertCodecPreset())
.Where(newPreset => newPreset != null)
.Cast<TDestination>()
.ToList();
}
}

View File

@@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodec;
using PepperDash.Essentials.Core.Presets;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
@@ -2185,7 +2186,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
}
public class RoomPreset
public class RoomPreset : ConvertiblePreset
{
public string id { get; set; }
public Defined Defined { get; set; }
@@ -2198,7 +2199,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
Description = new Description2();
Type = new Type5();
}
}
public override PresetBase ConvertCodecPreset()
{
try
{
var preset = new CodecRoomPreset(UInt16.Parse(id), Description.Value, Defined.BoolValue, true);
Debug.Console(2, "Preset ID {0} Converted from Cisco Codec Preset to Essentials Preset");
return preset;
}
catch (Exception e)
{
Debug.Console(2, "Unable to convert preset: {0}. Error: {1}", id, e);
return null;
}
}
}

View File

@@ -0,0 +1,9 @@
using PepperDash.Essentials.Core.Presets;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
public abstract class ConvertiblePreset
{
public abstract PresetBase ConvertCodecPreset();
}
}

View File

@@ -22,6 +22,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
void MinMaxLayoutToggle();
}
/// <summary>
/// Defines the required elements for layout control with direct layout selection
/// </summary>
public interface IHasCodecLayoutsAvailable : IHasCodecLayouts
{
event EventHandler<AvailableLayoutChangedEventArgs> AvailableLayoutsChanged;
StringFeedback AvailableLocalLayoutsFeedback { get; }
List<CodecCommandWithLabel> AvailableLocalLayouts { get; }
void LocalLayoutSet(string layout);
void LocalLayoutSet(CodecCommandWithLabel layout);
}
public class AvailableLayoutChangedEventArgs : EventArgs
{
public List<CodecCommandWithLabel> AvailableLayouts { get; set; }
}
/// <summary>
/// Defines the requirements for Zoom Room layout control
/// </summary>

View File

@@ -42,9 +42,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
public Boolean WaitingForHost { get; private set; }
[JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsLocked { get; private set; }
[JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsRecording { get; private set; }
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked)
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording)
{
Id = id;
Name = name;
@@ -55,6 +57,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
IsSharingMeeting = isSharingMeeting;
WaitingForHost = waitingForHost;
IsLocked = isLocked;
IsRecording = isRecording;
}
}

View File

@@ -15,4 +15,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
void StopRecording();
void ToggleRecording();
}
public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording
{
BoolFeedback RecordConsentPromptIsVisible { get; }
/// <summary>
/// Used to agree or disagree to the meeting being recorded when prompted
/// </summary>
/// <param name="agree"></param>
void RecordingPromptAcknowledgement(bool agree);
}
}

View File

@@ -24,6 +24,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary>
/// <param name="participant"></param>
void SetParticipantAsHost(int userId);
/// <summary>
/// Admits a participant from the waiting room
/// </summary>
/// <param name="userId"></param>
void AdmitParticipantFromWaitingRoom(int userId);
}
/// <summary>

View File

@@ -1,5 +1,5 @@
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{

View File

@@ -1,4 +1,4 @@
using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco;
using PepperDash.Essentials.Devices.Common.VideoCodec;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{

View File

@@ -10,6 +10,7 @@ using PepperDash.Core;
using PepperDash.Core.Intersystem;
using PepperDash.Core.Intersystem.Tokens;
using PepperDash.Core.WebApi.Presets;
using Crestron.SimplSharp.Reflection;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
@@ -370,6 +371,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap);
}
if (codec is IHasCodecLayoutsAvailable)
{
LinkVideoCodecAvailableLayoutsToApi(codec as IHasCodecLayoutsAvailable, trilist, joinMap);
}
if (codec is IHasSelfviewPosition)
{
LinkVideoCodecSelfviewPositionToApi(codec as IHasSelfviewPosition, trilist, joinMap);
@@ -457,10 +463,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
}
SharingContentIsOnFeedback.FireUpdate();
trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall);
trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig());
};
}
@@ -787,7 +789,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetSigFalseAction(joinMap.SourceShareStart.JoinNumber, StartSharing);
trilist.SetSigFalseAction(joinMap.SourceShareEnd.JoinNumber, StopSharing);
trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, (b) => AutoShareContentWhileInCall = b);
trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, b => AutoShareContentWhileInCall = b);
}
private List<Meeting> _currentMeetings = new List<Meeting>();
@@ -798,7 +800,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetUShortSigAction(joinMap.MinutesBeforeMeetingStart.JoinNumber, (i) =>
{
codec.CodecSchedule.MeetingWarningMinutes = i;
codec.CodecSchedule.MeetingWarningMinutes = i;
});
trilist.SetSigFalseAction(joinMap.DialMeeting1.JoinNumber, () =>
@@ -996,6 +998,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i, trilist, joinMap));
trilist.SetBoolSigAction(joinMap.DirectoryClearSelection.JoinNumber,
delegate { SelectDirectoryEntry(codec, 0, trilist, joinMap); });
// Report feedback for number of contact methods for selected contact
trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot);
@@ -1010,7 +1015,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot,
codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
@@ -1025,8 +1031,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(args.Directory, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
var directoryXSig = UpdateDirectoryXSig(args.Directory,
codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
@@ -1036,21 +1042,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC");
UpdateDirectoryXSig(codec.CurrentDirectoryResult,
!codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
var clearBytes = XSigHelpers.ClearOutputs();
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
};
}
private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
if (i < 1 || i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return;
_selectedDirectoryItem = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1];
if (i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return;
_selectedDirectoryItem = i == 0 ? null : codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1];
trilist.SetUshort(joinMap.DirectorySelectRow.JoinNumber, i);
if (_selectedDirectoryItem is DirectoryFolder)
{
@@ -1068,13 +1074,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty);
var selectedContact = _selectedDirectoryItem as DirectoryContact;
if (selectedContact != null)
{
trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, selectedContact.Name);
}
// Allow auto dial of selected line. Always dials first contact method
trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber,
selectedContact != null ? selectedContact.Name : string.Empty);
// Allow auto dial of selected line. Always dials first contact method
if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber))
{
var invitableEntry = _selectedDirectoryItem as IInvitableContact;
@@ -1087,12 +1091,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
var entryToDial = _selectedDirectoryItem as DirectoryContact;
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, selectedContact.ContactMethods[0].Number);
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber,
selectedContact != null ? selectedContact.ContactMethods[0].Number : string.Empty);
if (entryToDial == null) return;
Dial(entryToDial.ContactMethods[0].Number);
return;
}
else
{
@@ -1180,32 +1184,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot)
{
var contactIndex = 1;
var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count];
const int xSigMaxIndex = 1023;
var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex
? xSigMaxIndex
: directory.CurrentDirectoryResults.Count];
Debug.Console(2, this, "Is root {0} Directory Count: {1}", isRoot, directory.CurrentDirectoryResults.Count);
Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot, directory.CurrentDirectoryResults.Count, tokenArray.Length);
foreach (var entry in directory.CurrentDirectoryResults)
{
var arrayIndex = contactIndex - 1;
var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex
? directory.CurrentDirectoryResults.Take(xSigMaxIndex)
: directory.CurrentDirectoryResults;
Debug.Console(2, this, "Entry Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId);
var contactsToDisplay = isRoot
? contacts.Where(c => c.ParentFolderId == "root")
: contacts.Where(c => c.ParentFolderId != "root");
if (entry is DirectoryFolder && entry.ParentFolderId == "root")
{
tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, String.Format("[+] {0}", entry.Name));
var counterIndex = 1;
foreach (var entry in contactsToDisplay)
{
var arrayIndex = counterIndex - 1;
var entryIndex = counterIndex;
contactIndex++;
Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}, Type: {3}, ParentFolderId: {4}",
entry.Name, entry.FolderId, entryIndex, entry.GetType().GetCType().FullName, entry.ParentFolderId);
continue;
}
if (entry is DirectoryFolder)
{
tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name));
tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name);
counterIndex++;
contactIndex++;
}
continue;
}
return GetXSigString(tokenArray);
tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name);
counterIndex++;
}
return GetXSigString(tokenArray);
}
private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
@@ -1471,6 +1488,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentLayoutStringFb.JoinNumber]);
}
private void LinkVideoCodecAvailableLayoutsToApi(IHasCodecLayoutsAvailable codec, BasicTriList trilist,
VideoCodecControllerJoinMap joinMap)
{
codec.AvailableLocalLayoutsFeedback.LinkInputSig(trilist.StringInput[joinMap.AvailableLayoutsFb.JoinNumber]);
trilist.SetStringSigAction(joinMap.SelectLayout.JoinNumber, codec.LocalLayoutSet);
}
private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
trilist.SetSigFalseAction(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeOn);
@@ -1982,4 +2007,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
}
}
}
/// <summary>
/// Represents a codec command that might need to have a friendly label applied for UI feedback purposes
/// </summary>
public class CodecCommandWithLabel
{
public string Command { get; private set; }
public string Label { get; private set; }
public CodecCommandWithLabel(string command, string label)
{
Command = command;
Label = label;
}
}
}

View File

@@ -31,10 +31,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
else
{
Debug.Console(2, "PropertyChanged event is NULL");
}
}
#endregion
@@ -778,13 +783,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
set
{
//Debug.Console(2, "************************************setting value of meetingIsBeingRecorded to: {0}", value);
if (value != _meetingIsBeingRecorded)
{
_meetingIsBeingRecorded = value;
//Debug.Console(2, "********************************set value of meetingIsBeingRecorded to: {0}", _meetingIsBeingRecorded);
NotifyPropertyChanged("meetingIsBeingRecorded");
}
}
}
public CallRecordInfo()
{
Debug.Console(2, Debug.ErrorLogLevel.Notice, "********************************************* CallRecordInfo() ******************************************");
}
}
}

View File

@@ -27,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMuteWithUnmuteReqeust, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting,
IHasMeetingLock, IHasMeetingRecording
IHasMeetingLock, IHasMeetingRecordingWithPrompt
{
public event EventHandler VideoUnmuteRequested;
@@ -113,14 +113,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this);
Output1 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut,
Output1 = new RoutingOutputPort(RoutingPortNames.HdmiOut1,
eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
Output2 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut,
Output2 = new RoutingOutputPort(RoutingPortNames.HdmiOut2,
eRoutingSignalType.Video,
eRoutingPortConnectionType.DisplayPort, null, this);
Output3 = new RoutingOutputPort(RoutingPortNames.HdmiOut3,
eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc);
CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc);
@@ -170,6 +174,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable );
MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded );
RecordConsentPromptIsVisible = new BoolFeedback(() => _recordConsentPromptIsVisible);
SetUpRouting();
}
public CommunicationGather PortGather { get; private set; }
@@ -299,6 +307,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public RoutingInputPort CodecOsdIn { get; private set; }
public RoutingOutputPort Output1 { get; private set; }
public RoutingOutputPort Output2 { get; private set; }
public RoutingOutputPort Output3 { get; private set; }
#region ICommunicationMonitor Members
@@ -489,25 +498,63 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void SyncState_InitialSyncCompleted(object sender, EventArgs e)
{
SetUpRouting();
SetIsReady();
}
/// <summary>
/// Handles subscriptions to Status.Call and sub objects. Needs to be called whenever Status.Call is constructed
/// </summary>
private void SetUpCallFeedbackActions()
{
Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate;
Status.Call.Sharing.PropertyChanged -= HandleSharingStateUpdate;
Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate;
Status.Call.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "Info")
{
Debug.Console(1, this, "Updating Call Status");
UpdateCallStatus();
}
};
Status.Call.PropertyChanged -= HandleCallStateUpdate;
Status.Call.PropertyChanged += HandleCallStateUpdate;
Status.Call.CallRecordInfo.PropertyChanged -= HandleCallRecordInfoStateUpdate;
Status.Call.CallRecordInfo.PropertyChanged += HandleCallRecordInfoStateUpdate;
}
private void HandleCallRecordInfoStateUpdate(object sender, PropertyChangedEventArgs a)
{
if (a.PropertyName == "meetingIsBeingRecorded")
{
MeetingIsRecordingFeedback.FireUpdate();
var meetingInfo = new MeetingInfo(MeetingInfo.Id,
MeetingInfo.Name,
MeetingInfo.Host,
MeetingInfo.Password,
GetSharingStatus(),
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo;
}
}
private void HandleCallStateUpdate(object sender, PropertyChangedEventArgs a)
{
switch (a.PropertyName)
{
case "Info":
{
Debug.Console(1, this, "Updating Call Status");
UpdateCallStatus();
break;
}
case "Status":
{
UpdateCallStatus();
break;
}
}
}
private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a)
{
if (a.PropertyName != "State")
@@ -525,19 +572,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
var sharingStatus = GetSharingStatus();
MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue);
MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
return;
}
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None",
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue);
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo;
}
catch (Exception e)
{
Debug.Console(1, this, "Error processing state property update. {0}", e.Message);
Debug.Console(2, this, e.StackTrace);
MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue);
MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
}
}
@@ -546,6 +593,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// </summary>
private void SetUpFeedbackActions()
{
// Set these up initially.
SetUpCallFeedbackActions();
Configuration.Audio.Output.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "Volume")
@@ -640,7 +690,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingInfo.IsHost,
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue
);
}
};
@@ -673,41 +724,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
};
Status.Call.Sharing.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "State")
{
SharingContentIsOnFeedback.FireUpdate();
ReceivingContent.FireUpdate();
}
};
Status.Call.PropertyChanged += (o, a) =>
{
switch(a.PropertyName)
{
case "Info":
{
Debug.Console(1, this, "Updating Call Status");
UpdateCallStatus();
break;
}
case "Status":
{
UpdateCallStatus();
break;
}
}
};
Status.Call.CallRecordInfo.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "meetingIsBeingRecorded")
{
MeetingIsRecordingFeedback.FireUpdate();
}
};
Status.Sharing.PropertyChanged += (o, a) =>
{
@@ -739,7 +755,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue);
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo;
break;
}
@@ -1436,7 +1453,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue);
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo;
PrintCurrentCallParticipants();
@@ -1651,14 +1669,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (MeetingInfo == null)
{
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue);
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
UpdateCallStatus();
break;
}
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue);
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
UpdateCallStatus();
@@ -1668,12 +1686,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (MeetingInfo == null)
{
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue);
GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
break;
}
MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password,
GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue);
GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
break;
}
@@ -1682,12 +1700,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// TODO: notify user that host has disabled unmuting video
break;
}
case "updatedcallrecordinfo":
case "updatecallrecordinfo":
{
JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo);
break;
}
case "recordingconsent":
{
_recordConsentPromptIsVisible = responseObj["isShow"].Value<bool>();
RecordConsentPromptIsVisible.FireUpdate();
break;
}
case "phonecallstatus":
{
JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall);
@@ -1757,7 +1781,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (result.Success)
{
MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue);
MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
break;
}
@@ -1958,12 +1982,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// If not crrently in a meeting, intialize the call object
if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING)
{
//Debug.Console(1, this, "[UpdateCallStatus] Creating new Status.Call object");
Status.Call = new zStatus.Call {Status = callStatus};
// Resubscribe to all property change events after Status.Call is reconstructed
SetUpCallFeedbackActions();
OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected});
SetUpCallFeedbackActions();
}
if (ActiveCalls.Count == 0)
@@ -2103,7 +2126,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetIsHostMyself(),
!String.Equals(Status.Call.Info.meeting_type,"NORMAL"),
false,
MeetingIsLockedFeedback.BoolValue
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue
);
}
// TODO [ ] Issue #868
@@ -2118,6 +2142,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
false,
false,
false,
false,
false
);
}
@@ -2343,6 +2368,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <param name="joinMap"></param>
public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap)
{
var recordingCodec = this as IHasMeetingRecordingWithPrompt;
if (recordingCodec != null)
{
trilist.SetSigFalseAction(joinMap.StartRecording.JoinNumber, () => recordingCodec.StartRecording());
trilist.SetSigFalseAction(joinMap.StopRecording.JoinNumber, () => recordingCodec.StopRecording());
recordingCodec.MeetingIsRecordingFeedback.LinkInputSig(trilist.BooleanInput[joinMap.StartRecording.JoinNumber]);
recordingCodec.MeetingIsRecordingFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.StopRecording.JoinNumber]);
trilist.SetSigFalseAction(joinMap.RecordingPromptAgree.JoinNumber, () => recordingCodec.RecordingPromptAcknowledgement(true));
trilist.SetSigFalseAction(joinMap.RecordingPromptDisagree.JoinNumber, () => recordingCodec.RecordingPromptAcknowledgement(false));
recordingCodec.RecordConsentPromptIsVisible.LinkInputSig(trilist.BooleanInput[joinMap.RecordConsentPromptIsVisible.JoinNumber]);
}
var layoutsCodec = this as IHasZoomRoomLayouts;
if (layoutsCodec != null)
{
@@ -2796,6 +2836,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
SendText(string.Format("zCommand Call HostChange Id: {0}", userId));
}
public void AdmitParticipantFromWaitingRoom(int userId)
{
SendText(string.Format("zCommand Call Admit Participant Id: {0}", userId));
}
#endregion
#region IHasParticipantAudioMute Members
@@ -3406,18 +3451,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
#endregion
#region IHasMeetingRecording Members
#region IHasMeetingRecordingWithPrompt Members
public BoolFeedback MeetingIsRecordingFeedback { get; private set; }
bool _recordConsentPromptIsVisible;
public BoolFeedback RecordConsentPromptIsVisible { get; private set; }
public void RecordingPromptAcknowledgement(bool agree)
{
var command = string.Format("zCommand Agree Recording: {0}", agree ? "on" : "off");
//Debug.Console(2, this, "Sending agree: {0} {1}", agree, command);
SendText(command);
}
public void StartRecording()
{
SendText(string.Format("Command Call Record Enable: on"));
SendText(string.Format("zCommand Call Record Enable: on"));
}
public void StopRecording()
{
SendText(string.Format("Command Call Record Enable: off"));
SendText(string.Format("zCommand Call Record Enable: off"));
}
public void ToggleRecording()

View File

@@ -295,7 +295,77 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Description = "Toggles the selfview pip size, (aka layout size)",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
});
[JoinName("StartRecording")]
public JoinDataComplete StartRecording = new JoinDataComplete(
new JoinData
{
JoinNumber = 241,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to start the Meeting Recording. FB high if meeting is currently recording",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("StopRecording")]
public JoinDataComplete StopRecording = new JoinDataComplete(
new JoinData
{
JoinNumber = 242,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to stop the Meeting Recording. FB high if meeting is currently NOT recording",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordConsentPromptIsVisible")]
public JoinDataComplete RecordConsentPromptIsVisible = new JoinDataComplete(
new JoinData
{
JoinNumber = 243,
JoinSpan = 1
},
new JoinMetadata
{
Description = "When high, indicates that the recording consent prompt is visible on the ZoomRoom UI",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordingPromptAgree")]
public JoinDataComplete RecordingPromptAgree = new JoinDataComplete(
new JoinData
{
JoinNumber = 244,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to agree to consent for meeting recording",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordingPromptDisagree")]
public JoinDataComplete RecordingPromptDisagree = new JoinDataComplete(
new JoinData
{
JoinNumber = 245,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to disagree to consent for meeting recording",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
//[JoinName("ParticipantAudioMuteToggleStart")]
//public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete(

View File

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