diff --git a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
index 81be9002..dd454d97 100644
--- a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
+++ b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
@@ -948,5 +948,24 @@ namespace PepperDash.Essentials
/// 15214
///
public const uint PinDialogDot4 = 15214;
+
+ // Password Prompt Dialog **************************
+
+ ///
+ /// 15301
+ ///
+ public const uint PasswordPromptDialogVisible = 15301;
+ ///
+ /// 15302
+ ///
+ public const uint PasswordPromptTextPress = 15302;
+ ///
+ /// 15306
+ ///
+ public const uint PasswordPromptCancelPress = 15306;
+ ///
+ /// 15307
+ ///
+ public const uint PasswordPromptErrorVisible = 15307;
}
}
\ No newline at end of file
diff --git a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs
index 9b2b8a95..67a5c6e2 100644
--- a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs
+++ b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs
@@ -118,6 +118,14 @@ namespace PepperDash.Essentials
//----- through 3120
+ ///
+ /// 3201
+ ///
+ public const uint PasswordPromptMessageText = 3201;
+ ///
+ /// 3202
+ ///
+ public const uint PasswordPromptPasswordText = 3202;
///
/// 3812
diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs
index 8082a6cb..2d5bd1dd 100644
--- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs
+++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Collections.Generic;
+using System.Globalization;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.UI;
@@ -470,12 +471,16 @@ namespace PepperDash.Essentials
Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
CurrentRoom.OnFeedback.BoolValue,
LastMeetingDismissedId,
- lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToShortTimeString() : "");
+ lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : "");
var meeting = meetings.LastOrDefault(m => m.Joinable);
if (CurrentRoom.OnFeedback.BoolValue
&& lastMeetingDismissed == meeting)
{
+ // meeting no longer joinable, hide popup
+ if(meeting == null)
+ HideNextMeetingPopup();
+
return;
}
@@ -487,9 +492,11 @@ namespace PepperDash.Essentials
}
else
{
+
+
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Upcoming meeting");
- TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToShortTimeString());
- TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToShortTimeString());
+ TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToString("t", Global.Culture));
+ TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToString("t", Global.Culture));
TriList.SetString(UIStringJoin.NextMeetingTitleText, meeting.Title);
TriList.SetString(UIStringJoin.NextMeetingNameText, meeting.Organizer);
TriList.SetString(UIStringJoin.NextMeetingButtonLabel, "Join");
@@ -512,7 +519,7 @@ namespace PepperDash.Essentials
// indexOf = 3, 4 meetings :
if (indexOfNext < meetings.Count)
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText,
- meetings[indexOfNext].StartTime.ToShortTimeString());
+ meetings[indexOfNext].StartTime.ToString("t", Global.Culture));
else
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, "No more meetings today");
@@ -1209,8 +1216,8 @@ namespace PepperDash.Essentials
foreach (var m in CurrentRoom.ScheduleSource.CodecSchedule.Meetings)
{
i++;
- MeetingOrContactMethodModalSrl.StringInputSig(i, 1).StringValue = m.StartTime.ToShortTimeString();
- MeetingOrContactMethodModalSrl.StringInputSig(i, 2).StringValue = m.EndTime.ToShortTimeString();
+ MeetingOrContactMethodModalSrl.StringInputSig(i, 1).StringValue = m.StartTime.ToString("t", Global.Culture);
+ MeetingOrContactMethodModalSrl.StringInputSig(i, 2).StringValue = m.EndTime.ToString("t", Global.Culture);
MeetingOrContactMethodModalSrl.StringInputSig(i, 3).StringValue = m.Title;
MeetingOrContactMethodModalSrl.StringInputSig(i, 4).StringValue = string.Format("
{0}",m.Organizer);
MeetingOrContactMethodModalSrl.StringInputSig(i, 5).StringValue = "Join";
diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs
index 612f7eeb..f3f707c3 100644
--- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs
+++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Globalization;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
@@ -83,6 +84,9 @@ namespace PepperDash.Essentials.UIDrivers.VC
StringBuilder SearchStringBuilder = new StringBuilder();
BoolFeedback SearchStringBackspaceVisibleFeedback;
+ StringFeedback PasswordStringFeedback;
+ StringBuilder PasswordStringBuilder = new StringBuilder();
+
ModalDialog IncomingCallModal;
eKeypadMode KeypadMode;
@@ -180,8 +184,22 @@ namespace PepperDash.Essentials.UIDrivers.VC
});
SearchStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.CodecDirectorySearchEntryText]);
- SetupDirectoryList();
+ PasswordStringFeedback = new StringFeedback(() =>
+ {
+ if (PasswordStringBuilder.Length > 0)
+ {
+ Parent.Keyboard.EnableGoButton();
+ return PasswordStringBuilder.ToString();
+ }
+ else
+ {
+ Parent.Keyboard.DisableGoButton();
+ return "";
+ }
+ });
+ PasswordStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.PasswordPromptPasswordText]);
+ SetupDirectoryList();
SearchStringBackspaceVisibleFeedback = new BoolFeedback(() => SearchStringBuilder.Length > 0);
SearchStringBackspaceVisibleFeedback.LinkInputSig(triList.BooleanInput[UIBoolJoin.VCDirectoryBackspaceVisible]);
@@ -199,6 +217,12 @@ namespace PepperDash.Essentials.UIDrivers.VC
triList.SetSigHeldAction(UIBoolJoin.VCDirectoryBackspacePress, 500,
StartSearchBackspaceRepeat, StopSearchBackspaceRepeat, SearchKeypadBackspacePress);
+
+ if (Codec is IPasswordPrompt)
+ {
+ SetupPasswordPrompt();
+ }
+
}
catch (Exception e)
{
@@ -299,6 +323,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
{
case eCodecCallStatus.Connected:
// fire at SRL item
+ HidePasswordPrompt();
KeypadMode = eKeypadMode.DTMF;
DialStringBuilder.Remove(0, DialStringBuilder.Length);
DialStringFeedback.FireUpdate();
@@ -984,7 +1009,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
// if it's today, show a simpler string
string timeText = null;
if (c.StartTime.Date == DateTime.Now.Date)
- timeText = c.StartTime.ToShortTimeString();
+ timeText = c.StartTime.ToString("t", Global.Culture);
else if (c.StartTime == DateTime.MinValue)
timeText = "";
else
@@ -1328,7 +1353,21 @@ namespace PepperDash.Essentials.UIDrivers.VC
///
void RevealKeyboard()
{
- if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCKeypadWithFavoritesVisible && KeypadMode == eKeypadMode.Dial)
+ if (_passwordPromptDialogVisible)
+ {
+ Debug.Console(2, "Attaching Keyboard to PasswordPromptDialog");
+ DetachDialKeyboard();
+ DetachSearchKeyboard();
+ var kb = Parent.Keyboard;
+ kb.KeyPress -= Keyboard_PasswordKeyPress;
+ kb.KeyPress += Keyboard_PasswordKeyPress;
+ kb.HideAction = this.DetachPasswordKeyboard;
+ kb.GoButtonText = "Submit";
+ kb.GoButtonVisible = true;
+ PasswordStringCheckEnables();
+ kb.Show();
+ }
+ else if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCKeypadWithFavoritesVisible && KeypadMode == eKeypadMode.Dial)
{
var kb = Parent.Keyboard;
kb.KeyPress -= Keyboard_DialKeyPress;
@@ -1350,6 +1389,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
SearchStringKeypadCheckEnables();
kb.Show();
}
+
}
///
@@ -1405,6 +1445,32 @@ namespace PepperDash.Essentials.UIDrivers.VC
}
}
+ ///
+ /// Event handler for keyboard dialing
+ ///
+ void Keyboard_PasswordKeyPress(object sender, PepperDash.Essentials.Core.Touchpanels.Keyboards.KeyboardControllerPressEventArgs e)
+ {
+ if (_passwordPromptDialogVisible)
+ {
+ if (e.Text != null)
+ PasswordStringBuilder.Append(e.Text);
+ else
+ {
+ if (e.SpecialKey == KeyboardSpecialKey.Backspace)
+ PasswordKeypadBackspacePress();
+ else if (e.SpecialKey == KeyboardSpecialKey.Clear)
+ PasswordKeypadClear();
+ else if (e.SpecialKey == KeyboardSpecialKey.GoButton)
+ {
+ (Codec as IPasswordPrompt).SubmitPassword(PasswordStringBuilder.ToString());
+ HidePasswordPrompt();
+ }
+ }
+ PasswordStringFeedback.FireUpdate();
+ PasswordStringCheckEnables();
+ }
+ }
+
///
/// Call
///
@@ -1418,6 +1484,11 @@ namespace PepperDash.Essentials.UIDrivers.VC
Parent.Keyboard.KeyPress -= Keyboard_SearchKeyPress;
}
+ void DetachPasswordKeyboard()
+ {
+ Parent.Keyboard.KeyPress -= Keyboard_PasswordKeyPress;
+ }
+
///
/// Shows the camera controls subpage
///
@@ -1671,6 +1742,40 @@ namespace PepperDash.Essentials.UIDrivers.VC
Parent.Keyboard.DisableGoButton();
}
+ ///
+ /// Clears the Password keypad
+ ///
+ void PasswordKeypadClear()
+ {
+ PasswordStringBuilder.Remove(0, SearchStringBuilder.Length);
+ PasswordStringFeedback.FireUpdate();
+ PasswordStringCheckEnables();
+
+ }
+
+ ///
+ ///
+ ///
+ void PasswordKeypadBackspacePress()
+ {
+ PasswordStringBuilder.Remove(PasswordStringBuilder.Length - 1, 1);
+
+ PasswordStringFeedback.FireUpdate();
+ PasswordStringCheckEnables();
+ }
+
+ ///
+ /// Checks the enabled states of various elements around the keypad
+ ///
+ void PasswordStringCheckEnables()
+ {
+ var textIsEntered = PasswordStringBuilder.Length > 0;
+ if (textIsEntered)
+ Parent.Keyboard.EnableGoButton();
+ else
+ Parent.Keyboard.DisableGoButton();
+ }
+
///
/// Returns the text value for the keypad dial entry field
@@ -1716,5 +1821,61 @@ namespace PepperDash.Essentials.UIDrivers.VC
Dial = 0,
DTMF
}
+
+ void SetupPasswordPrompt()
+ {
+ var passwordPromptCodec = Codec as IPasswordPrompt;
+
+ passwordPromptCodec.PasswordRequired += new EventHandler(passwordPromptCodec_PasswordRequired);
+
+ TriList.SetSigFalseAction(UIBoolJoin.PasswordPromptCancelPress, HidePasswordPrompt);
+ TriList.SetSigFalseAction(UIBoolJoin.PasswordPromptTextPress, RevealKeyboard);
+ }
+
+ void passwordPromptCodec_PasswordRequired(object sender, PasswordPromptEventArgs e)
+ {
+ if (e.LoginAttemptCancelled)
+ {
+ HidePasswordPrompt();
+ return;
+ }
+
+ if (!string.IsNullOrEmpty(e.Message))
+ {
+ TriList.SetString(UIStringJoin.PasswordPromptMessageText, e.Message);
+ }
+
+ if (e.LoginAttemptFailed)
+ {
+ // TODO: Show a message modal to indicate the login attempt failed
+ return;
+ }
+
+ TriList.SetBool(UIBoolJoin.PasswordPromptErrorVisible, e.LastAttemptWasIncorrect);
+
+ ShowPasswordPrompt();
+ }
+
+ private bool _passwordPromptDialogVisible;
+
+ void ShowPasswordPrompt()
+ {
+ // Clear out any previous data
+ PasswordKeypadClear();
+
+ _passwordPromptDialogVisible = true;
+ TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible);
+ RevealKeyboard();
+ }
+
+ void HidePasswordPrompt()
+ {
+ if (_passwordPromptDialogVisible)
+ {
+ _passwordPromptDialogVisible = false;
+ Parent.Keyboard.Hide();
+ TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs
new file mode 100644
index 00000000..6ecdd775
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPasswordPrompt.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+namespace PepperDash.Essentials.Core
+{
+ ///
+ /// Describes the functionality required to prompt a user to enter a password
+ ///
+ public interface IPasswordPrompt
+ {
+ ///
+ /// Notifies when a password is required or is entered incorrectly
+ ///
+ event EventHandler PasswordRequired;
+
+ ///
+ /// Submits the password
+ ///
+ ///
+ void SubmitPassword(string password);
+ }
+
+ public class PasswordPromptEventArgs : EventArgs
+ {
+ ///
+ /// Indicates if the last submitted password was incorrect
+ ///
+ public bool LastAttemptWasIncorrect { get; private set; }
+
+ ///
+ /// Indicates that the login attempt has failed
+ ///
+ public bool LoginAttemptFailed { get; private set; }
+
+ ///
+ /// Indicates that the process was cancelled and the prompt should be dismissed
+ ///
+ public bool LoginAttemptCancelled { get; private set; }
+
+ ///
+ /// A message to be displayed to the user
+ ///
+ public string Message { get; private set; }
+
+ public PasswordPromptEventArgs(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message)
+ {
+ LastAttemptWasIncorrect = lastAttemptIncorrect;
+ LoginAttemptFailed = loginFailed;
+ LoginAttemptCancelled = loginCancelled;
+ Message = message;
+ }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs
index aa71c1f7..121bc9b7 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs
@@ -1,5 +1,6 @@
using System;
using System.Text.RegularExpressions;
+using System.Globalization;
using Crestron.SimplSharp;
using System.Collections.Generic;
using Crestron.SimplSharp.CrestronIO;
@@ -28,6 +29,10 @@ namespace PepperDash.Essentials.Core
public static eCrestronSeries ProcessorSeries { get { return CrestronEnvironment.ProgramCompatibility; } }
+ // TODO: consider making this configurable later
+ public static IFormatProvider Culture = CultureInfo.CreateSpecificCulture("en-US");
+
+
///
/// The file path prefix to the folder containing configuration files
///
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
index bde91605..abd7c498 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
@@ -203,6 +203,7 @@
+
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs
index da1685cc..a241d60d 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs
@@ -1,40 +1,40 @@
-using Crestron.SimplSharpPro;
-using System;
-using System.Linq;
-//using Crestron.SimplSharpPro.DeviceSupport;
-using Crestron.SimplSharpPro.DeviceSupport;
-using Crestron.SimplSharpPro.DM;
-using Crestron.SimplSharpPro.DM.Endpoints;
-using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
-
-using PepperDash.Core;
-using PepperDash.Essentials.Core;
-using PepperDash.Essentials.Core.Bridges;
-
-namespace PepperDash.Essentials.DM
-{
- using eVst = eX02VideoSourceType;
+using Crestron.SimplSharpPro;
+using System;
+using System.Linq;
+//using Crestron.SimplSharpPro.DeviceSupport;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Crestron.SimplSharpPro.DM;
+using Crestron.SimplSharpPro.DM.Endpoints;
+using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
+
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.Bridges;
+
+namespace PepperDash.Essentials.DM
+{
+ using eVst = eX02VideoSourceType;
using eAst = eX02AudioSourceType;
- public class DmTx4kz202CController : DmTxControllerBase, ITxRoutingWithFeedback,
- IIROutputPorts, IComPorts
- {
- public DmTx4kz202C Tx { get; private set; }
-
- public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; }
- public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; }
- public RoutingOutputPort DmOut { get; private set; }
- public RoutingOutputPort HdmiLoopOut { get; private set; }
-
- public override StringFeedback ActiveVideoInputFeedback { get; protected set; }
- public IntFeedback VideoSourceNumericFeedback { get; protected set; }
- public IntFeedback AudioSourceNumericFeedback { get; protected set; }
- public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; }
- public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; }
- public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; }
- public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
-
- //public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
+ public class DmTx4kz202CController : DmTxControllerBase, ITxRoutingWithFeedback,
+ IIROutputPorts, IComPorts
+ {
+ public DmTx4kz202C Tx { get; private set; }
+
+ public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; }
+ public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; }
+ public RoutingOutputPort DmOut { get; private set; }
+ public RoutingOutputPort HdmiLoopOut { get; private set; }
+
+ public override StringFeedback ActiveVideoInputFeedback { get; protected set; }
+ public IntFeedback VideoSourceNumericFeedback { get; protected set; }
+ public IntFeedback AudioSourceNumericFeedback { get; protected set; }
+ public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; }
+ public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; }
+ public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; }
+ public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
+
+ //public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
//public override ushort HdcpSupportCapability { get; protected set; }
//IroutingNumericEvent
public event EventHandler NumericSwitchChange;
@@ -47,48 +47,48 @@ namespace PepperDash.Essentials.DM
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
- }
-
-
-
- ///
- /// Helps get the "real" inputs, including when in Auto
- ///
- public eX02VideoSourceType ActualActiveVideoInput
- {
- get
- {
- if (Tx.VideoSourceFeedback != eVst.Auto)
- return Tx.VideoSourceFeedback;
-
- if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
- return eVst.Hdmi1;
-
- return Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue ? eVst.Hdmi2 : eVst.AllDisabled;
- }
- }
- public RoutingPortCollection InputPorts
- {
- get
- {
- return new RoutingPortCollection
- {
- HdmiIn1,
- HdmiIn2,
- AnyVideoInput
- };
- }
- }
- public RoutingPortCollection OutputPorts
- {
- get
- {
- return new RoutingPortCollection { DmOut, HdmiLoopOut };
- }
- }
- public DmTx4kz202CController(string key, string name, DmTx4kz202C tx)
- : base(key, name, tx)
- {
+ }
+
+
+
+ ///
+ /// Helps get the "real" inputs, including when in Auto
+ ///
+ public eX02VideoSourceType ActualActiveVideoInput
+ {
+ get
+ {
+ if (Tx.VideoSourceFeedback != eVst.Auto)
+ return Tx.VideoSourceFeedback;
+
+ if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
+ return eVst.Hdmi1;
+
+ return Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue ? eVst.Hdmi2 : eVst.AllDisabled;
+ }
+ }
+ public RoutingPortCollection InputPorts
+ {
+ get
+ {
+ return new RoutingPortCollection
+ {
+ HdmiIn1,
+ HdmiIn2,
+ AnyVideoInput
+ };
+ }
+ }
+ public RoutingPortCollection OutputPorts
+ {
+ get
+ {
+ return new RoutingPortCollection { DmOut, HdmiLoopOut };
+ }
+ }
+ public DmTx4kz202CController(string key, string name, DmTx4kz202C tx)
+ : base(key, name, tx)
+ {
Tx = tx;
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
@@ -104,208 +104,208 @@ namespace PepperDash.Essentials.DM
FeedbackMatchObject = eVst.Hdmi2
};
- ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
- () => ActualActiveVideoInput.ToString());
-
-
-
- Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
- Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
- Tx.BaseEvent += Tx_BaseEvent;
- Tx.OnlineStatusChange += Tx_OnlineStatusChange;
-
- VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
-
- //Return VideoSourceFeedback here as DM-TX-4KZ-202-C does not support audio breakaway
- AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
-
- HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback);
-
- HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
-
- HdcpStateFeedback =
- new IntFeedback(
- () =>
- tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback
- ? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback
- : (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
-
- HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
-
- Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
-
- Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue);
-
- var combinedFuncs = new VideoStatusFuncsWrapper
- {
- HdcpActiveFeedbackFunc = () =>
- (ActualActiveVideoInput == eVst.Hdmi1
- && tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue)
- || (ActualActiveVideoInput == eVst.Hdmi2
- && tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue),
-
- HdcpStateFeedbackFunc = () =>
- {
- if (ActualActiveVideoInput == eVst.Hdmi1)
- return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
- if (ActualActiveVideoInput == eVst.Hdmi2)
- return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString();
- return "";
- },
-
- VideoResolutionFeedbackFunc = () =>
- {
- if (ActualActiveVideoInput == eVst.Hdmi1)
- return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
- if (ActualActiveVideoInput == eVst.Hdmi2)
- return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
- return "";
- },
- VideoSyncFeedbackFunc = () =>
- (ActualActiveVideoInput == eVst.Hdmi1
- && tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
- || (ActualActiveVideoInput == eVst.Hdmi2
- && tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
-
- };
-
- AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn,
- eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs);
-
- DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.DmCat, null, this);
- HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.Hdmi, null, this);
-
-
- AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
- AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
- AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
- AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback,
- Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback);
-
- // Set Ports for CEC
- HdmiIn1.Port = Tx.HdmiInputs[1];
- HdmiIn2.Port = Tx.HdmiInputs[2];
- HdmiLoopOut.Port = Tx.HdmiOutput;
- DmOut.Port = Tx.DmOutput;
- }
-
-
-
- public override bool CustomActivate()
- {
- // Link up all of these damned events to the various RoutingPorts via a helper handler
- Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId);
- Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId);
-
- Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId);
- Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId);
-
- // Base does register and sets up comm monitoring.
- return base.CustomActivate();
- }
-
- public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
- {
- var joinMap = GetDmTxJoinMap(joinStart, joinMapKey);
-
- if (Hdmi1VideoSyncFeedback != null)
- {
- Hdmi1VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input1VideoSyncStatus.JoinNumber]);
- }
- if (Hdmi2VideoSyncFeedback != null)
- {
- Hdmi2VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input2VideoSyncStatus.JoinNumber]);
- }
-
- LinkDmTxToApi(this, trilist, joinMap, bridge);
- }
-
- public void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type)
- {
- Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input);
-
- switch (type)
- {
- case eRoutingSignalType.Video:
- switch (input)
- {
- case 0:
- {
- ExecuteSwitch(eVst.Auto, null, type);
- break;
- }
- case 1:
- {
- ExecuteSwitch(HdmiIn1.Selector, null, type);
- break;
- }
- case 2:
- {
- ExecuteSwitch(HdmiIn2.Selector, null, type);
- break;
- }
- case 3:
- {
- ExecuteSwitch(eVst.AllDisabled, null, type);
- break;
- }
- }
- break;
- case eRoutingSignalType.Audio:
- switch (input)
- {
- case 0:
- {
- ExecuteSwitch(eAst.Auto, null, type);
- break;
- }
- case 1:
- {
- ExecuteSwitch(eAst.Hdmi1, null, type);
- break;
- }
- case 2:
- {
- ExecuteSwitch(eAst.Hdmi2, null, type);
- break;
- }
- case 3:
- {
- ExecuteSwitch(eAst.AllDisabled, null, type);
- break;
- }
- }
- break;
- }
- }
-
- public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
- {
- if ((signalType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
- Tx.VideoSource = (eVst)inputSelector;
- if(((signalType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio))
- Debug.Console(2, this, "Unable to execute audio-only switch for tx {0}", Key);
- }
-
- void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
- {
- Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString());
-
- switch (args.EventId)
- {
- case EndpointInputStreamEventIds.HdcpSupportOffFeedbackEventId:
- case EndpointInputStreamEventIds.HdcpSupportOnFeedbackEventId:
- case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId:
- if (inputStream == Tx.HdmiInputs[1]) HdmiIn1HdcpCapabilityFeedback.FireUpdate();
- if (inputStream == Tx.HdmiInputs[2]) HdmiIn2HdcpCapabilityFeedback.FireUpdate();
- break;
- case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId:
- if (inputStream == Tx.HdmiInputs[1]) Hdmi1VideoSyncFeedback.FireUpdate();
- if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
- break;
- }
+ ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
+ () => ActualActiveVideoInput.ToString());
+
+
+
+ Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
+ Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
+ Tx.BaseEvent += Tx_BaseEvent;
+ Tx.OnlineStatusChange += Tx_OnlineStatusChange;
+
+ VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
+
+ //Return VideoSourceFeedback here as DM-TX-4KZ-202-C does not support audio breakaway
+ AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
+
+ HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback);
+
+ HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
+
+ HdcpStateFeedback =
+ new IntFeedback(
+ () =>
+ tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback
+ ? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback
+ : (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
+
+ HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
+
+ Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
+
+ Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue);
+
+ var combinedFuncs = new VideoStatusFuncsWrapper
+ {
+ HdcpActiveFeedbackFunc = () =>
+ (ActualActiveVideoInput == eVst.Hdmi1
+ && tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue)
+ || (ActualActiveVideoInput == eVst.Hdmi2
+ && tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue),
+
+ HdcpStateFeedbackFunc = () =>
+ {
+ if (ActualActiveVideoInput == eVst.Hdmi1)
+ return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
+ if (ActualActiveVideoInput == eVst.Hdmi2)
+ return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString();
+ return "";
+ },
+
+ VideoResolutionFeedbackFunc = () =>
+ {
+ if (ActualActiveVideoInput == eVst.Hdmi1)
+ return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
+ if (ActualActiveVideoInput == eVst.Hdmi2)
+ return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
+ return "";
+ },
+ VideoSyncFeedbackFunc = () =>
+ (ActualActiveVideoInput == eVst.Hdmi1
+ && tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
+ || (ActualActiveVideoInput == eVst.Hdmi2
+ && tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
+
+ };
+
+ AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn,
+ eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs);
+
+ DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.DmCat, null, this);
+ HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Hdmi, null, this);
+
+
+ AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
+ AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
+ AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
+ AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback,
+ Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback);
+
+ // Set Ports for CEC
+ HdmiIn1.Port = Tx.HdmiInputs[1];
+ HdmiIn2.Port = Tx.HdmiInputs[2];
+ HdmiLoopOut.Port = Tx.HdmiOutput;
+ DmOut.Port = Tx.DmOutput;
+ }
+
+
+
+ public override bool CustomActivate()
+ {
+ // Link up all of these damned events to the various RoutingPorts via a helper handler
+ Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId);
+ Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId);
+
+ Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId);
+ Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId);
+
+ // Base does register and sets up comm monitoring.
+ return base.CustomActivate();
+ }
+
+ public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
+ {
+ var joinMap = GetDmTxJoinMap(joinStart, joinMapKey);
+
+ if (Hdmi1VideoSyncFeedback != null)
+ {
+ Hdmi1VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input1VideoSyncStatus.JoinNumber]);
+ }
+ if (Hdmi2VideoSyncFeedback != null)
+ {
+ Hdmi2VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input2VideoSyncStatus.JoinNumber]);
+ }
+
+ LinkDmTxToApi(this, trilist, joinMap, bridge);
+ }
+
+ public void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type)
+ {
+ Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input);
+
+ switch (type)
+ {
+ case eRoutingSignalType.Video:
+ switch (input)
+ {
+ case 0:
+ {
+ ExecuteSwitch(eVst.Auto, null, type);
+ break;
+ }
+ case 1:
+ {
+ ExecuteSwitch(HdmiIn1.Selector, null, type);
+ break;
+ }
+ case 2:
+ {
+ ExecuteSwitch(HdmiIn2.Selector, null, type);
+ break;
+ }
+ case 3:
+ {
+ ExecuteSwitch(eVst.AllDisabled, null, type);
+ break;
+ }
+ }
+ break;
+ case eRoutingSignalType.Audio:
+ switch (input)
+ {
+ case 0:
+ {
+ ExecuteSwitch(eAst.Auto, null, type);
+ break;
+ }
+ case 1:
+ {
+ ExecuteSwitch(eAst.Hdmi1, null, type);
+ break;
+ }
+ case 2:
+ {
+ ExecuteSwitch(eAst.Hdmi2, null, type);
+ break;
+ }
+ case 3:
+ {
+ ExecuteSwitch(eAst.AllDisabled, null, type);
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
+ {
+ if ((signalType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
+ Tx.VideoSource = (eVst)inputSelector;
+ if(((signalType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio))
+ Debug.Console(2, this, "Unable to execute audio-only switch for tx {0}", Key);
+ }
+
+ void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
+ {
+ Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString());
+
+ switch (args.EventId)
+ {
+ case EndpointInputStreamEventIds.HdcpSupportOffFeedbackEventId:
+ case EndpointInputStreamEventIds.HdcpSupportOnFeedbackEventId:
+ case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId:
+ if (inputStream == Tx.HdmiInputs[1]) HdmiIn1HdcpCapabilityFeedback.FireUpdate();
+ if (inputStream == Tx.HdmiInputs[2]) HdmiIn2HdcpCapabilityFeedback.FireUpdate();
+ break;
+ case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId:
+ if (inputStream == Tx.HdmiInputs[1]) Hdmi1VideoSyncFeedback.FireUpdate();
+ if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
+ break;
+ }
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
@@ -313,7 +313,7 @@ namespace PepperDash.Essentials.DM
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
- InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
+ InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
@@ -338,68 +338,68 @@ namespace PepperDash.Essentials.DM
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
- var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
- Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ Debug.Console(2, this, " Audio Source: {0}", Tx.VideoSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
- }
-
- ///
- /// Relays the input stream change to the appropriate RoutingInputPort.
- ///
- void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
- {
- if (eventId != EndpointInputStreamEventIds.SyncDetectedFeedbackEventId)
- {
- return;
- }
- inputPort.VideoStatus.VideoSyncFeedback.FireUpdate();
- AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate();
- }
-
- ///
- /// Relays the VideoAttributes change to a RoutingInputPort
- ///
- void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
- {
- //// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds
- //Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}",
- // args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType());
- switch (eventId)
- {
- case VideoAttributeEventIds.HdcpActiveFeedbackEventId:
- inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate();
- AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate();
- break;
- case VideoAttributeEventIds.HdcpStateFeedbackEventId:
- inputPort.VideoStatus.HdcpStateFeedback.FireUpdate();
- AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate();
- break;
- case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId:
- case VideoAttributeEventIds.VerticalResolutionFeedbackEventId:
- inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
- AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
- break;
- case VideoAttributeEventIds.FramesPerSecondFeedbackEventId:
- inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
- AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
- break;
- }
- }
-
-
-
-
- #region IIROutputPorts Members
- public CrestronCollection IROutputPorts { get { return Tx.IROutputPorts; } }
- public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } }
- #endregion
-
- #region IComPorts Members
- public CrestronCollection ComPorts { get { return Tx.ComPorts; } }
- public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } }
- #endregion
- }
+ }
+
+ ///
+ /// Relays the input stream change to the appropriate RoutingInputPort.
+ ///
+ void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
+ {
+ if (eventId != EndpointInputStreamEventIds.SyncDetectedFeedbackEventId)
+ {
+ return;
+ }
+ inputPort.VideoStatus.VideoSyncFeedback.FireUpdate();
+ AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate();
+ }
+
+ ///
+ /// Relays the VideoAttributes change to a RoutingInputPort
+ ///
+ void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
+ {
+ //// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds
+ //Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}",
+ // args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType());
+ switch (eventId)
+ {
+ case VideoAttributeEventIds.HdcpActiveFeedbackEventId:
+ inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate();
+ AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate();
+ break;
+ case VideoAttributeEventIds.HdcpStateFeedbackEventId:
+ inputPort.VideoStatus.HdcpStateFeedback.FireUpdate();
+ AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate();
+ break;
+ case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId:
+ case VideoAttributeEventIds.VerticalResolutionFeedbackEventId:
+ inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
+ AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
+ break;
+ case VideoAttributeEventIds.FramesPerSecondFeedbackEventId:
+ inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
+ AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
+ break;
+ }
+ }
+
+
+
+
+ #region IIROutputPorts Members
+ public CrestronCollection IROutputPorts { get { return Tx.IROutputPorts; } }
+ public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } }
+ #endregion
+
+ #region IComPorts Members
+ public CrestronCollection ComPorts { get { return Tx.ComPorts; } }
+ public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } }
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs
index fb8f3ac5..70df8259 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs
@@ -339,7 +339,7 @@ namespace PepperDash.Essentials.DM
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
- InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
+ InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
@@ -364,8 +364,8 @@ namespace PepperDash.Essentials.DM
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
- var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
- Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ Debug.Console(2, this, " Audio Source: {0}", Tx.VideoSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs
index 29a46466..b2ccb29c 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs
@@ -160,7 +160,19 @@ namespace PepperDash.Essentials.Devices.Common.Codec
///
public interface IInvitableContact
{
+ bool IsInvitableContact { get; }
+ }
+ public class InvitableDirectoryContact : DirectoryContact, IInvitableContact
+ {
+ [JsonProperty("isInvitableContact")]
+ public bool IsInvitableContact
+ {
+ get
+ {
+ return this is IInvitableContact;
+ }
+ }
}
///
@@ -209,8 +221,6 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("title")]
public string Title { get; set; }
-
-
[JsonProperty("contactMethods")]
public List ContactMethods { get; set; }
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
index 21821d22..75d01b0f 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
@@ -123,6 +123,7 @@
+
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs
index bce321b9..f894141c 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs
@@ -743,6 +743,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
+ ///
+ /// Appends the delimiter and send the command to the codec
+ ///
+ ///
public void SendText(string command)
{
if (CommDebuggingIsOn)
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs
new file mode 100644
index 00000000..a01ec099
--- /dev/null
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/Interfaces/IHasStartMeeting.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
+{
+ ///
+ /// Describes the ability to start an ad-hoc meeting
+ ///
+ public interface IHasStartMeeting
+ {
+ ///
+ /// The default meeting duration in minutes
+ ///
+ uint DefaultMeetingDurationMin { get; }
+
+ ///
+ /// Start an ad-hoc meeting for the specified duration
+ ///
+ ///
+ void StartMeeting(uint duration);
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs
index c5cff74e..d34c9e3b 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs
@@ -836,10 +836,10 @@ ScreenIndexIsPinnedTo: {8} (a{17})
//serials
tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer);
tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title);
- tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToShortDateString());
- tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToShortTimeString());
- tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToShortDateString());
- tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToShortTimeString());
+ tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString("t", Global.Culture));
+ tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString("t", Global.Culture));
+ tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString("t", Global.Culture));
+ tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString("t", Global.Culture));
tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id);
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs
index c116a4a8..28073eb8 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs
@@ -236,14 +236,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
- ///
- /// Used to be able to inplement IInvitableContact on DirectoryContact
- ///
- public class ZoomDirectoryContact : DirectoryContact, IInvitableContact
- {
-
- }
-
public class Phonebook
{
[JsonProperty("Contacts")]
@@ -302,7 +294,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
foreach (Contact c in zoomContacts)
{
- var contact = new ZoomDirectoryContact { Name = c.ScreenName, ContactId = c.Jid };
+ var contact = new InvitableDirectoryContact { Name = c.ScreenName, ContactId = c.Jid };
contact.ContactMethods.Add(new ContactMethod() { Number = c.Jid, Device = eContactMethodDevice.Video, CallType = eContactMethodCallType.Video, ContactMethodId = c.Jid });
@@ -927,6 +919,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
PhoneCallStatus_InCall,
PhoneCallStatus_Init,
}
+
+ public class MeetingNeedsPassword
+ {
+ [JsonProperty("needsPassword")]
+ public bool NeedsPassword { get; set; }
+
+ [JsonProperty("wrongAndRetry")]
+ public bool WrongAndRetry { get; set; }
+ }
}
///
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs
index 5473cbb8..1b1a9629 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs
@@ -25,10 +25,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
IRouting,
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
- IHasParticipantAudioMute, IHasSelfviewSize
+ IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting
{
private const long MeetingRefreshTimer = 60000;
- private const uint DefaultMeetingDurationMin = 30;
+ public uint DefaultMeetingDurationMin { get; private set; }
+
private const string Delimiter = "\x0D\x0A";
private readonly GenericQueue _receiveQueue;
@@ -45,12 +46,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private StringBuilder _jsonMessage;
private int _previousVolumeLevel;
private CameraBase _selectedCamera;
+ private string _lastDialedMeetingNumber;
private readonly ZoomRoomPropertiesConfig _props;
public ZoomRoom(DeviceConfig config, IBasicCommunication comm)
: base(config)
{
+ DefaultMeetingDurationMin = 30;
+
_props = JsonConvert.DeserializeObject(config.Properties.ToString());
_receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512);
@@ -730,7 +734,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
ConsoleAccessLevelEnum.AccessOperator);
if (!_props.DisablePhonebookAutoDownload)
{
- CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"),
+ CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 10000"),
"GetZoomRoomContacts", "Triggers a refresh of the codec phonebook",
ConsoleAccessLevelEnum.AccessOperator);
}
@@ -860,7 +864,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (!_props.DisablePhonebookAutoDownload)
{
- _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 512");
+ _syncState.AddQueryToQueue("zCommand Phonebook List Offset: 0 Limit: 10000");
}
_syncState.AddQueryToQueue("zCommand Bookings List");
@@ -1358,7 +1362,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
case "meetingneedspassword":
{
- // TODO: notify user to enter a password
+ var meetingNeedsPassword =
+ responseObj.ToObject();
+
+ if (meetingNeedsPassword.NeedsPassword)
+ {
+ var prompt = "Password required to join this meeting. Please enter the meeting password.";
+
+ OnPasswordRequired(meetingNeedsPassword.WrongAndRetry, false, false, prompt);
+ }
+ else
+ {
+ OnPasswordRequired(false, false, true, "");
+ }
+
break;
}
case "needwaitforhost":
@@ -2050,9 +2067,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public override void Dial(string number)
{
+ _lastDialedMeetingNumber = number;
SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number));
}
+ ///
+ /// Dials a meeting with a password
+ ///
+ ///
+ ///
+ public void Dial(string number, string password)
+ {
+ Debug.Console(2, this, "Dialing meeting number: {0} with password: {1}", number, password);
+ SendText(string.Format("zCommand Dial Join meetingNumber: {0} password: {1}", number, password));
+ }
+
///
/// Invites a contact to either a new meeting (if not already in a meeting) or the current meeting.
/// Currently only invites a single user
@@ -2060,7 +2089,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
///
public override void Dial(IInvitableContact contact)
{
- var ic = contact as zStatus.ZoomDirectoryContact;
+ var ic = contact as InvitableDirectoryContact;
if (ic != null)
{
@@ -2078,6 +2107,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
+
+ ///
+ /// Starts a PMI Meeting for the specified duration (or default meeting duration if 0 is specified)
+ ///
+ /// duration of meeting
+ public void StartMeeting(uint duration)
+ {
+ uint dur = DefaultMeetingDurationMin;
+
+ if (duration > 0)
+ dur = duration;
+
+ SendText(string.Format("zCommand Dial StartPmi Duration: {0}", dur));
+ }
+
public override void EndCall(CodecActiveCallItem call)
{
SendText("zCommand Call Disconnect");
@@ -2681,7 +2725,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
#endregion
- }
+
+ #region IPasswordPrompt Members
+
+ public event EventHandler PasswordRequired;
+
+ public void SubmitPassword(string password)
+ {
+ Debug.Console(2, this, "Password Submitted: {0}", password);
+ Dial(_lastDialedMeetingNumber, password);
+ }
+
+ void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message)
+ {
+ var handler = PasswordRequired;
+ if (handler != null)
+ {
+ handler(this, new PasswordPromptEventArgs(lastAttemptIncorrect, loginFailed, loginCancelled, message));
+ }
+ }
+
+ #endregion
+ }
///
/// Zoom Room specific info object