Merge remote-tracking branch 'PepperDash_Essentials/development' into feature/dmps-endpoint-fixes

This commit is contained in:
Alex Johnson
2021-09-23 12:01:33 -04:00
26 changed files with 1504 additions and 611 deletions

View File

@@ -8,6 +8,7 @@ $destination = "$($Env:GITHUB_HOME)\output"
New-Item -ItemType Directory -Force -Path ($destination) New-Item -ItemType Directory -Force -Path ($destination)
Get-ChildItem ($destination) Get-ChildItem ($destination)
$exclusions = @(git submodule foreach --quiet 'echo $name') $exclusions = @(git submodule foreach --quiet 'echo $name')
$exclusions += "Newtonsoft.Compact.Json.dll"
# Trying to get any .json schema files (not currently working) # Trying to get any .json schema files (not currently working)
# Gets any files with the listed extensions. # Gets any files with the listed extensions.
Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.dll", "*.nuspec" | ForEach-Object { Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz", "*.cplz", "*.dll", "*.nuspec" | ForEach-Object {

View File

@@ -48,6 +48,11 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public const uint MeetingNameText = 1009; public const uint MeetingNameText = 1009;
///<summary>
/// 1240 - Used to determine text for meeting start button
///</summary>
public const uint MeetingStartButtonText = 1240;

View File

@@ -7,7 +7,7 @@
{ {
// Video Codec // Video Codec
/// <summary> /// <summary>
/// 1234: values 0 = Connect, 1 = End /// 1234: values 0 = Connect, 1 = End, 2 = Start Meeting
/// </summary> /// </summary>
public const uint VCStagingConnectButtonMode = 1234; public const uint VCStagingConnectButtonMode = 1234;

View File

@@ -12,6 +12,7 @@ using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.SmartObjects; using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.PageManagers; using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
using PepperDash.Essentials.Room.Config; using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec; using PepperDash.Essentials.Devices.Common.VideoCodec;
@@ -191,32 +192,56 @@ namespace PepperDash.Essentials
return; return;
} }
var meetingInfoCodec = codec as IHasMeetingInfo;
// Set mode of header button // Set mode of header button
SetHeaderCallIcon(codec);
// Set the call status text
Debug.Console(1, "Active Call Count: {0}", codec.ActiveCalls.Count);
if (codec.ActiveCalls.Count > 0)
{
if (codec.ActiveCalls.Count == 1 && meetingInfoCodec == null)
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "1 Active Call");
else if (codec.ActiveCalls.Count == 1 && meetingInfoCodec != null)
{
var headerCallStatusLabel = meetingInfoCodec.MeetingInfo.IsSharingMeeting
? "Sharing-Only Meeting"
: "Active Meeting";
headerCallStatusLabel = meetingInfoCodec.MeetingInfo.WaitingForHost
? "Waiting For Host"
: headerCallStatusLabel;
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, headerCallStatusLabel);
}
else if (codec.ActiveCalls.Count > 1)
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, string.Format("{0} Active Calls", codec.ActiveCalls.Count));
}
else
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "No Active Calls");
}
private void SetHeaderCallIcon(VideoCodecBase codec)
{
if (!codec.IsInCall) if (!codec.IsInCall)
{ {
HeaderCallButtonIconSig.StringValue = "DND"; HeaderCallButtonIconSig.StringValue = "DND";
//HeaderCallButton.SetIcon(HeaderListButton.OnHook); //HeaderCallButton.SetIcon(HeaderListButton.OnHook);
} }
else if (codec.ActiveCalls.Any(c => c.Type == eCodecCallType.Video)) else if (codec.ActiveCalls.Any(c => c.Type == eCodecCallType.Video))
{
HeaderCallButtonIconSig.StringValue = "Misc-06_Dark"; HeaderCallButtonIconSig.StringValue = "Misc-06_Dark";
//HeaderCallButton.SetIcon(HeaderListButton.Camera); }
//TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 2); //HeaderCallButton.SetIcon(HeaderListButton.Camera);
//TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 2);
else else
{
HeaderCallButtonIconSig.StringValue = "Misc-09_Dark"; HeaderCallButtonIconSig.StringValue = "Misc-09_Dark";
}
//HeaderCallButton.SetIcon(HeaderListButton.Phone); //HeaderCallButton.SetIcon(HeaderListButton.Phone);
//TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 1); //TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 1);
// Set the call status text
Debug.Console(1, "Active Call Count: {0}", codec.ActiveCalls.Count);
if (codec.ActiveCalls.Count > 0)
{
if (codec.ActiveCalls.Count == 1)
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "1 Active Call");
else if (codec.ActiveCalls.Count > 1)
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, string.Format("{0} Active Calls", codec.ActiveCalls.Count));
}
else
TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "No Active Calls");
} }
/// <summary> /// <summary>

View File

@@ -9,6 +9,7 @@ using Crestron.SimplSharpPro.UI;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.SmartObjects; using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.PageManagers; using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.Room.Config; using PepperDash.Essentials.Room.Config;
@@ -471,85 +472,92 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
void ShowNextMeetingTimerCallback() void ShowNextMeetingTimerCallback()
{ {
//Update calendar for Zoom. Zoom doesn't automatically update when meetings are in the past
if (_isZoomRoomWithNoExternalSources)
{
CurrentRoom.ScheduleSource.GetSchedule();
}
// Every 60 seconds, refresh the calendar // Every 60 seconds, refresh the calendar
RefreshMeetingsList(); RefreshMeetingsList();
// check meetings list for the closest, joinable meeting // check meetings list for the closest, joinable meeting
var ss = CurrentRoom.ScheduleSource; var ss = CurrentRoom.ScheduleSource;
var meetings = ss.CodecSchedule.Meetings; var meetings = ss.CodecSchedule.Meetings;
if (meetings.Count > 0) if (meetings.Count <= 0)
{ {
// If the room is off pester the user return;
// If the room is on, and the meeting is joinable }
// and the LastMeetingDismissed != this meeting // If the room is off pester the user
// If the room is on, and the meeting is joinable
// and the LastMeetingDismissed != this meeting
var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId); var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId);
Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
CurrentRoom.OnFeedback.BoolValue, CurrentRoom.OnFeedback.BoolValue,
LastMeetingDismissedId, LastMeetingDismissedId,
lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : ""); lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : "");
var meeting = meetings.LastOrDefault(m => m.Joinable); var meeting = meetings.LastOrDefault(m => m.Joinable);
if (CurrentRoom.OnFeedback.BoolValue if (CurrentRoom.OnFeedback.BoolValue
&& lastMeetingDismissed == meeting) && lastMeetingDismissed == meeting)
{ {
// meeting no longer joinable, hide popup // meeting no longer joinable, hide popup
if(meeting == null) if(meeting == null)
HideNextMeetingPopup(); HideNextMeetingPopup();
return; return;
} }
LastMeetingDismissedId = null; LastMeetingDismissedId = null;
// Clear the popup when we run out of meetings // Clear the popup when we run out of meetings
if (meeting == null) if (meeting == null)
{ {
HideNextMeetingPopup(); HideNextMeetingPopup();
} }
else else
{ {
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Upcoming meeting"); TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Upcoming meeting");
TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToString("t", Global.Culture)); TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToString("t", Global.Culture));
TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToString("t", Global.Culture)); TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToString("t", Global.Culture));
TriList.SetString(UIStringJoin.NextMeetingTitleText, meeting.Title); TriList.SetString(UIStringJoin.NextMeetingTitleText, meeting.Title);
TriList.SetString(UIStringJoin.NextMeetingNameText, meeting.Organizer); TriList.SetString(UIStringJoin.NextMeetingNameText, meeting.Organizer);
TriList.SetString(UIStringJoin.NextMeetingButtonLabel, "Join"); TriList.SetString(UIStringJoin.NextMeetingButtonLabel, "Join");
TriList.SetSigFalseAction(UIBoolJoin.NextMeetingJoinPress, () => TriList.SetSigFalseAction(UIBoolJoin.NextMeetingJoinPress, () =>
{ {
HideNextMeetingPopup(); HideNextMeetingPopup();
PopupInterlock.Hide(); PopupInterlock.Hide();
RoomOnAndDialMeeting(meeting); RoomOnAndDialMeeting(meeting);
}); });
TriList.SetString(UIStringJoin.NextMeetingSecondaryButtonLabel, "Show Schedule"); TriList.SetString(UIStringJoin.NextMeetingSecondaryButtonLabel, "Show Schedule");
TriList.SetSigFalseAction(UIBoolJoin.CalendarHeaderButtonPress, () => TriList.SetSigFalseAction(UIBoolJoin.CalendarHeaderButtonPress, () =>
{ {
HideNextMeetingPopup(); HideNextMeetingPopup();
//CalendarPress(); //CalendarPress();
RefreshMeetingsList(); RefreshMeetingsList();
PopupInterlock.ShowInterlocked(UIBoolJoin.MeetingsOrContacMethodsListVisible); PopupInterlock.ShowInterlocked(UIBoolJoin.MeetingsOrContacMethodsListVisible);
}); });
var indexOfNext = meetings.IndexOf(meeting) + 1; var indexOfNext = meetings.IndexOf(meeting) + 1;
// indexOf = 3, 4 meetings : // indexOf = 3, 4 meetings :
if (indexOfNext < meetings.Count) if (indexOfNext < meetings.Count)
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText,
meetings[indexOfNext].StartTime.ToString("t", Global.Culture)); meetings[indexOfNext].StartTime.ToString("t", Global.Culture));
else else
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, "No more meetings today"); TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, "No more meetings today");
TriList.SetSigFalseAction(UIBoolJoin.NextMeetingModalClosePress, () => TriList.SetSigFalseAction(UIBoolJoin.NextMeetingModalClosePress, () =>
{ {
// Mark the meeting to not re-harass the user // Mark the meeting to not re-harass the user
if(CurrentRoom.OnFeedback.BoolValue) if(CurrentRoom.OnFeedback.BoolValue)
LastMeetingDismissedId = meeting.Id; LastMeetingDismissedId = meeting.Id;
HideNextMeetingPopup(); HideNextMeetingPopup();
}); });
TriList.SetBool(UIBoolJoin.NextMeetingModalVisible, true); TriList.SetBool(UIBoolJoin.NextMeetingModalVisible, true);
} }
}
} }
/// <summary> /// <summary>
@@ -575,19 +583,26 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
void RoomOnAndDialMeeting(Meeting meeting) void RoomOnAndDialMeeting(Meeting meeting)
{ {
Debug.Console(1, "[RoomOnAndDialMeeting] Joining meeting [{0}]", meeting);
Action dialAction = () => Action dialAction = () =>
{ {
var d = CurrentRoom.ScheduleSource as VideoCodecBase; var d = CurrentRoom.ScheduleSource as VideoCodecBase;
if (d != null) if (d != null)
{ {
Debug.Console(1,
"[RoomOnAndDialMeeting] [dialAction] Sending command to codec to join meeting {0}", meeting);
d.Dial(meeting); d.Dial(meeting);
LastMeetingDismissedId = meeting.Id; // To prevent prompts for already-joined call LastMeetingDismissedId = meeting.Id; // To prevent prompts for already-joined call
} }
}; };
if (CurrentRoom.OnFeedback.BoolValue) if (CurrentRoom.OnFeedback.BoolValue)
dialAction(); {
Debug.Console(1, "[RoomOnAndDialMeeting] Room is on.");
dialAction();
}
else else
{ {
Debug.Console(1, "RoomOnAndDialMeeting] Room is off or warming. Registering for Warming Feedback");
// Rig a one-time handler to catch when the room is warmed and then dial call // Rig a one-time handler to catch when the room is warmed and then dial call
EventHandler<FeedbackEventArgs> oneTimeHandler = null; EventHandler<FeedbackEventArgs> oneTimeHandler = null;
oneTimeHandler = (o, a) => oneTimeHandler = (o, a) =>
@@ -716,10 +731,32 @@ namespace PepperDash.Essentials
if (_isZoomRoomWithNoExternalSources) if (_isZoomRoomWithNoExternalSources)
{ {
(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute(); if (!CurrentRoom.OnFeedback.BoolValue)
{
CurrentRoom.RunDefaultPresentRoute();
}
// For now, if this is a Zoom Room and there are no shareable sources just display the informational subpage // For now, if this is a Zoom Room and there are no shareable sources just display the informational subpage
TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, true); TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, true);
var presentationMeetingCodec = CurrentRoom.VideoCodec as IHasPresentationOnlyMeeting;
var farEndContentStatusCodec = CurrentRoom.VideoCodec as IHasFarEndContentStatus;
var receivingContent = false;
if (farEndContentStatusCodec != null)
{
receivingContent = farEndContentStatusCodec.ReceivingContent.BoolValue;
}
if (presentationMeetingCodec != null && !CurrentRoom.VideoCodec.IsInCall)
{
presentationMeetingCodec.StartSharingOnlyMeeting(eSharingMeetingMode.Laptop);
}
else if (CurrentRoom.VideoCodec.IsInCall && !CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue &&
!receivingContent)
{
CurrentRoom.VideoCodec.StartSharing();
}
if (CurrentSourcePageManager != null) if (CurrentSourcePageManager != null)
CurrentSourcePageManager.Hide(); CurrentSourcePageManager.Hide();
} }
@@ -734,7 +771,9 @@ namespace PepperDash.Essentials
} }
else // room is on show what's active or select a source if nothing is yet active else // room is on show what's active or select a source if nothing is yet active
{ {
if (CurrentRoom.CurrentSourceInfo == null || (CurrentRoom.VideoCodec != null && CurrentRoom.CurrentSourceInfo.SourceDevice.Key == CurrentRoom.VideoCodec.OsdSource.Key)) if (CurrentRoom.CurrentSourceInfo == null ||
(CurrentRoom.VideoCodec != null &&
CurrentRoom.CurrentSourceInfo.SourceDevice.Key == CurrentRoom.VideoCodec.OsdSource.Key))
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
else if (CurrentSourcePageManager != null) else if (CurrentSourcePageManager != null)
{ {
@@ -1079,13 +1118,18 @@ namespace PepperDash.Essentials
void meetingInfoCodec_MeetingInfoChanged(object sender, MeetingInfoEventArgs e) void meetingInfoCodec_MeetingInfoChanged(object sender, MeetingInfoEventArgs e)
{ {
if (e.Info == null)
{
return;
}
TriList.SetString(UIStringJoin.MeetingIdText, e.Info.Id); TriList.SetString(UIStringJoin.MeetingIdText, e.Info.Id);
TriList.SetString(UIStringJoin.MeetingHostText, e.Info.Host); TriList.SetString(UIStringJoin.MeetingHostText, e.Info.Host);
TriList.SetString(UIStringJoin.MeetingNameText, e.Info.Name); TriList.SetString(UIStringJoin.MeetingNameText, e.Info.Name);
TriList.SetString(UIStringJoin.MeetingPasswordText, e.Info.Password); TriList.SetString(UIStringJoin.MeetingPasswordText, e.Info.Password);
// Show the password fields if one is present // Show the password fields if one is present
TriList.SetBool(UIBoolJoin.MeetingPasswordVisible, string.IsNullOrEmpty(e.Info.Password) ? false : true); TriList.SetBool(UIBoolJoin.MeetingPasswordVisible, !string.IsNullOrEmpty(e.Info.Password));
TriList.SetString(UIStringJoin.CallSharedSourceNameText, e.Info.ShareStatus); TriList.SetString(UIStringJoin.CallSharedSourceNameText, e.Info.ShareStatus);
@@ -1295,9 +1339,8 @@ namespace PepperDash.Essentials
{ {
// See if this is helpful or if the callback response in the codec class maybe doesn't come it time? // See if this is helpful or if the callback response in the codec class maybe doesn't come it time?
// Let's build list from event // Let's build list from event
// CurrentRoom.ScheduleSource.GetSchedule();
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListIcon, "Calendar"); TriList.SetString(UIStringJoin.MeetingsOrContactMethodListIcon, "Calendar");
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Today's Meetings"); TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Today's Meetings");
ushort i = 0; ushort i = 0;

View File

@@ -134,11 +134,12 @@ namespace PepperDash.Essentials.UIDrivers.VC
VCControlsInterlock = new JoinedSigInterlock(triList); VCControlsInterlock = new JoinedSigInterlock(triList);
VCCameraControlModeInterlock = new JoinedSigInterlock(triList); VCCameraControlModeInterlock = new JoinedSigInterlock(triList);
VCControlsInterlock.HideAndClear();
if (CodecHasFavorites) /* if (CodecHasFavorites || codec is IHasZoomRoomLayouts) //Checking for Zoom Room...picked a ZoomRoom specific interface to check for
VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadWithFavoritesVisible); VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadWithFavoritesVisible);
else else
VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadVisible); VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadVisible); */
StagingBarsInterlock = new JoinedSigInterlock(triList); StagingBarsInterlock = new JoinedSigInterlock(triList);
if(Codec is IHasCallHistory) if(Codec is IHasCallHistory)
@@ -320,25 +321,20 @@ namespace PepperDash.Essentials.UIDrivers.VC
void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{ {
var call = e.CallItem; var call = e.CallItem;
var meetingInfoSender = sender as IHasMeetingInfo;
switch (e.CallItem.Status) switch (e.CallItem.Status)
{ {
case eCodecCallStatus.Connected: case eCodecCallStatus.Connected:
// fire at SRL item // fire at SRL item
HidePasswordPrompt();
KeypadMode = eKeypadMode.DTMF;
DialStringBuilder.Remove(0, DialStringBuilder.Length);
DialStringFeedback.FireUpdate();
DialStringTextCheckEnables();
Parent.ShowNotificationRibbon("Connected", 2000); Parent.ShowNotificationRibbon("Connected", 2000);
StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress); OnCallConnected();
ShowKeypad();
((Parent.CurrentRoom as IHasCurrentVolumeControls).CurrentVolumeControls as IBasicVolumeWithFeedback).MuteOff();
//VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCKeypadVisible); //VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCKeypadVisible);
break; break;
case eCodecCallStatus.Connecting: case eCodecCallStatus.Connecting:
// fire at SRL item // fire at SRL item
Parent.ShowNotificationRibbon("Connecting", 0); Parent.ShowNotificationRibbon("Connecting", 0);
OnCallConnected();
break; break;
case eCodecCallStatus.Dialing: case eCodecCallStatus.Dialing:
Parent.ShowNotificationRibbon("Connecting", 0); Parent.ShowNotificationRibbon("Connecting", 0);
@@ -354,7 +350,10 @@ namespace PepperDash.Essentials.UIDrivers.VC
DialStringBuilder.Remove(0, DialStringBuilder.Length); DialStringBuilder.Remove(0, DialStringBuilder.Length);
DialStringFeedback.FireUpdate(); DialStringFeedback.FireUpdate();
Parent.ShowNotificationRibbon("Disconnected", 2000); Parent.ShowNotificationRibbon("Disconnected", 2000);
Debug.Console(0, "Setting Connect Button mode to 0");
} }
break; break;
case eCodecCallStatus.Disconnecting: case eCodecCallStatus.Disconnecting:
break; break;
@@ -375,12 +374,23 @@ namespace PepperDash.Essentials.UIDrivers.VC
ShowIncomingModal(call); ShowIncomingModal(call);
break; break;
} }
default:
break;
} }
TriList.UShortInput[UIUshortJoin.VCStagingConnectButtonMode].UShortValue = (ushort)(Codec.IsInCall ? 1 : 0);
if (meetingInfoSender != null && Codec.IsInCall)
uint stageJoin; {
var meetingInfo = meetingInfoSender.MeetingInfo;
TriList.UShortInput[UIUshortJoin.VCStagingConnectButtonMode].UShortValue =
(ushort) (meetingInfo.IsSharingMeeting ? 2 : 1);
}
else
{
TriList.UShortInput[UIUshortJoin.VCStagingConnectButtonMode].UShortValue =
(ushort) (Codec.IsInCall ? 1 : 0);
}
uint stageJoin;
if (Codec.IsInCall) if (Codec.IsInCall)
stageJoin = UIBoolJoin.VCStagingActivePopoverVisible; stageJoin = UIBoolJoin.VCStagingActivePopoverVisible;
else else
@@ -401,6 +411,36 @@ namespace PepperDash.Essentials.UIDrivers.VC
UpdateHeaderActiveCallList(); UpdateHeaderActiveCallList();
} }
private void OnCallConnected()
{
HidePasswordPrompt();
KeypadMode = eKeypadMode.DTMF;
DialStringBuilder.Remove(0, DialStringBuilder.Length);
DialStringFeedback.FireUpdate();
DialStringTextCheckEnables();
StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress);
ShowKeypad();
UnmuteRoomOnCallConnect();
}
private void UnmuteRoomOnCallConnect()
{
var volControl = Parent.CurrentRoom as IHasCurrentVolumeControls;
if (volControl == null)
{
return;
}
var currentVolControls = volControl.CurrentVolumeControls as IBasicVolumeWithFeedback;
if (currentVolControls != null)
{
currentVolControls.MuteOff();
}
}
/// <summary> /// <summary>
/// Redraws the calls list on the header /// Redraws the calls list on the header
/// </summary> /// </summary>
@@ -519,14 +559,35 @@ namespace PepperDash.Essentials.UIDrivers.VC
TriList.SetSigFalseAction(UIBoolJoin.VCStagingMeetNowPress, MeetNowPress); TriList.SetSigFalseAction(UIBoolJoin.VCStagingMeetNowPress, MeetNowPress);
TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, CallStopSharingPress); TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, CallStopSharingPress);
var meetingInfoCodec = Codec as IHasMeetingInfo;
TriList.SetSigFalseAction(UIBoolJoin.CallEndPress, () => TriList.SetSigFalseAction(UIBoolJoin.CallEndPress, () =>
{ {
if (Codec.ActiveCalls.Count > 1) if (Codec.ActiveCalls.Count > 1)
{ {
Parent.PopupInterlock.ShowInterlocked(Parent.CallListOrMeetingInfoPopoverVisibilityJoin); Parent.PopupInterlock.ShowInterlocked(Parent.CallListOrMeetingInfoPopoverVisibilityJoin);
} }
else if (meetingInfoCodec != null && Codec.ActiveCalls.Count == 1)
{
var meetingInfo = meetingInfoCodec.MeetingInfo;
if (meetingInfo != null && meetingInfo.IsSharingMeeting)
{
var presentationMeetingCodec = Codec as IHasPresentationOnlyMeeting;
if (presentationMeetingCodec != null)
{
presentationMeetingCodec.StartNormalMeetingFromSharingOnlyMeeting();
}
}
else
{
Codec.EndAllCalls();
}
}
else else
{
Codec.EndAllCalls(); Codec.EndAllCalls();
}
}); });
TriList.SetSigFalseAction(UIBoolJoin.CallEndAllConfirmPress, () => TriList.SetSigFalseAction(UIBoolJoin.CallEndAllConfirmPress, () =>
@@ -535,7 +596,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
Codec.EndAllCalls(); Codec.EndAllCalls();
}); });
var meetingInfoCodec = Codec as IHasMeetingInfo;
if (meetingInfoCodec != null) if (meetingInfoCodec != null)
{ {
TriList.SetSigFalseAction(UIBoolJoin.MeetingLeavePress, () => TriList.SetSigFalseAction(UIBoolJoin.MeetingLeavePress, () =>
@@ -1801,7 +1862,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// </summary> /// </summary>
void PasswordKeypadClear() void PasswordKeypadClear()
{ {
PasswordStringBuilder.Remove(0, SearchStringBuilder.Length); PasswordStringBuilder.Remove(0, PasswordStringBuilder.Length);
PasswordStringFeedback.FireUpdate(); PasswordStringFeedback.FireUpdate();
PasswordStringCheckEnables(); PasswordStringCheckEnables();
@@ -1929,6 +1990,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
_passwordPromptDialogVisible = false; _passwordPromptDialogVisible = false;
Parent.Keyboard.Hide(); Parent.Keyboard.Hide();
TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible); TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible);
PasswordKeypadClear();
} }
} }
} }

View File

@@ -57,7 +57,7 @@ namespace PepperDash.Essentials.Core
public DescriptionAttribute(string description) public DescriptionAttribute(string description)
{ {
Debug.Console(2, "Setting Description: {0}", description); //Debug.Console(2, "Setting Description: {0}", description);
_Description = description; _Description = description;
} }
@@ -74,7 +74,7 @@ namespace PepperDash.Essentials.Core
public ConfigSnippetAttribute(string configSnippet) public ConfigSnippetAttribute(string configSnippet)
{ {
Debug.Console(2, "Setting Config Snippet {0}", configSnippet); //Debug.Console(2, "Setting Config Snippet {0}", configSnippet);
_ConfigSnippet = configSnippet; _ConfigSnippet = configSnippet;
} }
@@ -103,7 +103,7 @@ namespace PepperDash.Essentials.Core
{ {
foreach (var typeName in TypeNames) foreach (var typeName in TypeNames)
{ {
Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); //Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName);
var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[];
string description = descriptionAttribute[0].Description; string description = descriptionAttribute[0].Description;
var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[];

View File

@@ -69,13 +69,13 @@ namespace PepperDash.Essentials.Core
/// <returns></returns> /// <returns></returns>
public static void AddFactoryForType(string typeName, Func<DeviceConfig, IKeyed> method) public static void AddFactoryForType(string typeName, Func<DeviceConfig, IKeyed> method)
{ {
Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); //Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName);
DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method}); DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method});
} }
public static void AddFactoryForType(string typeName, string description, CType cType, Func<DeviceConfig, IKeyed> method) public static void AddFactoryForType(string typeName, string description, CType cType, Func<DeviceConfig, IKeyed> method)
{ {
Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); //Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName);
if(FactoryMethods.ContainsKey(typeName)) if(FactoryMethods.ContainsKey(typeName))
{ {

View File

@@ -14,7 +14,7 @@
<tags>crestron 3series 4series</tags> <tags>crestron 3series 4series</tags>
<repository type="git" url="https://github.com/PepperDash/Essentials"/> <repository type="git" url="https://github.com/PepperDash/Essentials"/>
<dependencies> <dependencies>
<dependency id="PepperDashCore" version="[1.0.45, 1.1.0)"/> <dependency id="PepperDashCore" version="[1.0.45, 2.0.0)"/>
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

View File

@@ -123,7 +123,7 @@ namespace PepperDash.Essentials
/// <param name="fileName"></param> /// <param name="fileName"></param>
static LoadedAssembly LoadAssembly(string filePath) static LoadedAssembly LoadAssembly(string filePath)
{ {
Debug.Console(2, "Attempting to load {0}", filePath); //Debug.Console(2, "Attempting to load {0}", filePath);
var assembly = Assembly.LoadFrom(filePath); var assembly = Assembly.LoadFrom(filePath);
if (assembly != null) if (assembly != null)
{ {

View File

@@ -8,6 +8,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM; using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Cards; using Crestron.SimplSharpPro.DM.Cards;
using Crestron.SimplSharpPro.DM.Endpoints; using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpProInternal;
using Newtonsoft.Json; using Newtonsoft.Json;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
@@ -482,6 +483,24 @@ namespace PepperDash.Essentials.DM
} }
private void RegisterForInputResolutionFeedback(IVideoAttributesBasic input, uint number, RoutingInputPortWithVideoStatuses inputPort)
{
if (input == null)
{
return;
}
Debug.Console(1, this, "Registering for resolution feedback for input {0} using Routing Port {1}", number, inputPort.Key);
input.VideoAttributes.AttributeChange += (sender, args) =>
{
Debug.Console(1, this, "Input {0} resolution updated", number);
Debug.Console(1, this, "Updating resolution feedback for input {0}", number);
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
};
}
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@@ -497,166 +516,189 @@ namespace PepperDash.Essentials.DM
{ {
case "dmchd": case "dmchd":
{ {
var inputCard = new DmcHd(number, this.Chassis); var inputCard = new DmcHd(number, Chassis);
var cecPort = inputCard.HdmiInput as ICec; AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
AddHdmiInCardPorts(number, cecPort);
} }
break; break;
case "dmchddsp": case "dmchddsp":
{ {
var inputCard = new DmcHdDsp(number, this.Chassis); var inputCard = new DmcHdDsp(number, Chassis);
var cecPort = inputCard.HdmiInput as ICec; AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
AddHdmiInCardPorts(number, cecPort);
} }
break; break;
case "dmc4khd": case "dmc4khd":
{ {
var inputCard = new Dmc4kHd(number, this.Chassis); var inputCard = new Dmc4kHd(number, Chassis);
var cecPort = inputCard.HdmiInput as ICec; AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
AddHdmiInCardPorts(number, cecPort);
} }
break; break;
case "dmc4khddsp": case "dmc4khddsp":
{ {
var inputCard = new Dmc4kHdDsp(number, this.Chassis); var inputCard = new Dmc4kHdDsp(number, Chassis);
var cecPort = inputCard.HdmiInput as ICec; AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
AddHdmiInCardPorts(number, cecPort);
} }
break; break;
case "dmc4kzhd": case "dmc4kzhd":
{ {
var inputCard = new Dmc4kzHd(number, this.Chassis); var inputCard = new Dmc4kzHd(number, Chassis);
var cecPort = inputCard.HdmiInput as ICec; AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
AddHdmiInCardPorts(number, cecPort);
}
break; break;
}
case "dmc4kzhddsp": case "dmc4kzhddsp":
{ {
var inputCard = new Dmc4kzHdDsp(number, this.Chassis); var inputCard = new Dmc4kzHdDsp(number, Chassis);
var cecPort = inputCard.HdmiInput as ICec; AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
AddHdmiInCardPorts(number, cecPort);
}
break; break;
}
case "dmcc": case "dmcc":
{ {
var inputCard = new DmcC(number, this.Chassis); var inputCard = new DmcC(number, Chassis);
var cecPort = inputCard.DmInput as ICec; //DmInput doesn't implement ICec...cast was resulting in null anyway
AddDmInCardPorts(number, cecPort); AddDmInCardPorts(number, null, inputCard.DmInput);
} }
break; break;
case "dmccdsp": case "dmccdsp":
{ {
var inputCard = new DmcCDsp(number, this.Chassis); var inputCard = new DmcCDsp(number, Chassis);
var cecPort = inputCard.DmInput as ICec; //DmInput doesn't implement ICec...cast was resulting in null anyway
AddDmInCardPorts(number, cecPort); AddDmInCardPorts(number, null, inputCard.DmInput);
}
break; break;
}
case "dmc4kc": case "dmc4kc":
{ {
var inputCard = new Dmc4kC(number, this.Chassis); var inputCard = new Dmc4kC(number, Chassis);
var cecPort = inputCard.DmInput as ICec; AddDmInCardPorts(number, inputCard.DmInput,inputCard.DmInput);
AddDmInCardPorts(number, cecPort);
}
break; break;
}
case "dmc4kcdsp": case "dmc4kcdsp":
{ {
var inputCard = new Dmc4kCDsp(number, this.Chassis); var inputCard = new Dmc4kCDsp(number, Chassis);
var cecPort = inputCard.DmInput as ICec; AddDmInCardPorts(number, inputCard.DmInput,inputCard.DmInput);
AddDmInCardPorts(number, cecPort);
}
break; break;
}
case "dmc4kzc": case "dmc4kzc":
{ {
var inputCard = new Dmc4kzC(number, this.Chassis); var inputCard = new Dmc4kzC(number, Chassis);
var cecPort = inputCard.DmInput as ICec; AddDmInCardPorts(number, inputCard.DmInput,inputCard.DmInput);
AddDmInCardPorts(number, cecPort);
}
break; break;
}
case "dmc4kzcdsp": case "dmc4kzcdsp":
{ {
var inputCard = new Dmc4kzCDsp(number, this.Chassis); var inputCard = new Dmc4kzCDsp(number, Chassis);
var cecPort = inputCard.DmInput as ICec; AddDmInCardPorts(number, inputCard.DmInput, inputCard.DmInput);
AddDmInCardPorts(number, cecPort); break;
} }
break;
case "dmccat": case "dmccat":
new DmcCat(number, this.Chassis); {
AddDmInCardPorts(number); var inputCard = new DmcCat(number, Chassis);
AddDmInCardPorts(number, null, inputCard.DmInput);
break; break;
}
case "dmccatdsp": case "dmccatdsp":
new DmcCatDsp(number, this.Chassis); {
AddDmInCardPorts(number); var inputCard = new DmcCatDsp(number, Chassis);
AddDmInCardPorts(number, null, inputCard.DmInput);
break; break;
}
case "dmcs": case "dmcs":
new DmcS(number, Chassis); {
AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber); var inputCard = new DmcS(number, Chassis);
AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber, null, inputCard.DmInput);
AddInCardHdmiAndAudioLoopPorts(number); AddInCardHdmiAndAudioLoopPorts(number);
break; break;
}
case "dmcsdsp": case "dmcsdsp":
new DmcSDsp(number, Chassis); {
AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber); var inputCard = new DmcSDsp(number, Chassis);
AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber, null, inputCard.DmInput);
AddInCardHdmiAndAudioLoopPorts(number); AddInCardHdmiAndAudioLoopPorts(number);
break; break;
}
case "dmcs2": case "dmcs2":
new DmcS2(number, Chassis); {
AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber); var inputCard = new DmcS2(number, Chassis);
AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber, null, inputCard.DmInput);
AddInCardHdmiAndAudioLoopPorts(number); AddInCardHdmiAndAudioLoopPorts(number);
break; break;
}
case "dmcs2dsp": case "dmcs2dsp":
new DmcS2Dsp(number, Chassis); {
AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber); var inputCard = new DmcS2Dsp(number, Chassis);
AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber, null, inputCard.DmInput);
AddInCardHdmiAndAudioLoopPorts(number); AddInCardHdmiAndAudioLoopPorts(number);
break; break;
}
case "dmcsdi": case "dmcsdi":
new DmcSdi(number, Chassis); {
AddInputPortWithDebug(number, "sdiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Sdi); var inputCard = new DmcSdi(number, Chassis);
AddInputPortWithDebug(number, "sdiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Sdi, null, inputCard.SdiInput);
AddOutputPortWithDebug(string.Format("inputCard{0}", number), "sdiOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, AddOutputPortWithDebug(string.Format("inputCard{0}", number), "sdiOut", eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Sdi, null); eRoutingPortConnectionType.Sdi, null);
AddInCardHdmiAndAudioLoopPorts(number); AddInCardHdmiAndAudioLoopPorts(number);
break; break;
}
case "dmcdvi": case "dmcdvi":
new DmcDvi(number, Chassis); {
AddInputPortWithDebug(number, "dviIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Dvi); var inputCard = new DmcDvi(number, Chassis);
AddInputPortWithDebug(number, "dviIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Dvi, null, inputCard.DviInput);
AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio);
AddInCardHdmiLoopPort(number); AddInCardHdmiLoopPort(number);
break; break;
}
case "dmcvga": case "dmcvga":
new DmcVga(number, Chassis); {
AddInputPortWithDebug(number, "vgaIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Vga); var inputCard = new DmcVga(number, Chassis);
AddInputPortWithDebug(number, "vgaIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, null, inputCard.VgaInput);
AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio);
AddInCardHdmiLoopPort(number); AddInCardHdmiLoopPort(number);
break; break;
}
case "dmcvidbnc": case "dmcvidbnc":
new DmcVidBnc(number, Chassis); {
AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component); var inputCard = new DmcVidBnc(number, Chassis);
AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component, null, inputCard.VideoInput);
AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio);
AddInCardHdmiLoopPort(number); AddInCardHdmiLoopPort(number);
break; break;
}
case "dmcvidrcaa": case "dmcvidrcaa":
new DmcVidRcaA(number, Chassis); {
AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component); var inputCard = new DmcVidRcaA(number, Chassis);
AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component, null, inputCard.VideoInput);
AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio);
AddInCardHdmiLoopPort(number); AddInCardHdmiLoopPort(number);
break; break;
}
case "dmcvidrcad": case "dmcvidrcad":
new DmcVidRcaD(number, Chassis); {
AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component); var inputCard = new DmcVidRcaD(number, Chassis);
AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component, null, inputCard.VideoInput);
AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio); AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio);
AddInCardHdmiLoopPort(number); AddInCardHdmiLoopPort(number);
break; break;
}
case "dmcvid4": case "dmcvid4":
new DmcVid4(number, Chassis); {
var inputCard = new DmcVid4(number, Chassis);
AddInputPortWithDebug(number, "compositeIn1", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); AddInputPortWithDebug(number, "compositeIn1", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite);
AddInputPortWithDebug(number, "compositeIn2", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); AddInputPortWithDebug(number, "compositeIn2", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite);
AddInputPortWithDebug(number, "compositeIn3", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); AddInputPortWithDebug(number, "compositeIn3", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite);
AddInputPortWithDebug(number, "compositeIn4", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); AddInputPortWithDebug(number, "compositeIn4", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite);
AddInCardHdmiLoopPort(number); AddInCardHdmiLoopPort(number);
break; break;
}
case "dmcstr": case "dmcstr":
new DmcStr(number, Chassis); {
AddInputPortWithDebug(number, "streamIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming); var inputCard = new DmcStr(number, Chassis);
AddInputPortWithDebug(number, "streamIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming, null, inputCard.Source);
AddInCardHdmiAndAudioLoopPorts(number); AddInCardHdmiAndAudioLoopPorts(number);
break; break;
}
} }
} }
@@ -672,12 +714,24 @@ namespace PepperDash.Essentials.DM
AddInCardHdmiAndAudioLoopPorts(number); AddInCardHdmiAndAudioLoopPorts(number);
} }
void AddDmInCardPorts(uint number, ICec cecPort, IVideoAttributesBasic videoAttributes)
{
AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort, videoAttributes);
AddInCardHdmiAndAudioLoopPorts(number);
}
void AddHdmiInCardPorts(uint number, ICec cecPort) void AddHdmiInCardPorts(uint number, ICec cecPort)
{ {
AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort); AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort);
AddInCardHdmiAndAudioLoopPorts(number); AddInCardHdmiAndAudioLoopPorts(number);
} }
void AddHdmiInCardPorts(uint number, ICec cecPort, IVideoAttributesBasic videoAttributes)
{
AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort, videoAttributes);
AddInCardHdmiAndAudioLoopPorts(number);
}
void AddInCardHdmiAndAudioLoopPorts(uint number) void AddInCardHdmiAndAudioLoopPorts(uint number)
{ {
AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video,
@@ -816,20 +870,55 @@ namespace PepperDash.Essentials.DM
/// </summary> /// </summary>
void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType) void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType)
{ {
AddInputPortWithDebug(cardNum, portName, sigType, portType, null); //Cast is necessary here to determine the correct overload
AddInputPortWithDebug(cardNum, portName, sigType, portType, null, null);
}
private void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType,
eRoutingPortConnectionType portType, ICec cecPort)
{
//Cast is necessary here to determine the correct overload
AddInputPortWithDebug(cardNum, portName, sigType, portType, cecPort, null);
} }
/// <summary> /// <summary>
/// Adds InputPort and sets Port as ICec object /// Adds InputPort and sets Port as ICec object. If videoAttributesBasic is defined, RoutingPort will be RoutingInputPortWithVideoStatuses
/// </summary> /// </summary>
void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort) void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort, IVideoAttributesBasic videoAttributesBasic)
{ {
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName); var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey); Debug.Console(2, this, "Adding input port '{0}'", portKey);
var inputPort = new RoutingInputPort(portKey, sigType, portType, Chassis.Inputs[cardNum], this)
RoutingInputPort inputPort;
if (videoAttributesBasic != null)
{ {
FeedbackMatchObject = Chassis.Inputs[cardNum] Debug.Console(1, this, "card {0} supports IVideoAttributesBasic", cardNum);
}; ; var statusFuncs = new VideoStatusFuncsWrapper
{
VideoResolutionFeedbackFunc = () =>
{
var resolution = videoAttributesBasic.VideoAttributes.GetVideoResolutionString();
Debug.Console(1, this, "Updating resolution for input {0}. New resolution: {1}", cardNum, resolution);
return resolution;
}
};
inputPort = new RoutingInputPortWithVideoStatuses(portKey, sigType, portType,
Chassis.Inputs[cardNum], this, statusFuncs)
{
FeedbackMatchObject = Chassis.Inputs[cardNum]
};
RegisterForInputResolutionFeedback(videoAttributesBasic, cardNum, inputPort as RoutingInputPortWithVideoStatuses);
}
else
{
inputPort = new RoutingInputPort(portKey, sigType, portType,
Chassis.Inputs[cardNum], this)
{
FeedbackMatchObject = Chassis.Inputs[cardNum]
};
}
if (cecPort != null) if (cecPort != null)
inputPort.Port = cecPort; inputPort.Port = cecPort;
@@ -989,6 +1078,23 @@ namespace PepperDash.Essentials.DM
Debug.Console(2, this, "No index of {0} found in InputStreamCardStateFeedbacks"); Debug.Console(2, this, "No index of {0} found in InputStreamCardStateFeedbacks");
break; break;
} }
case DMInputEventIds.HorizontalResolutionFeedbackEventId:
case DMInputEventIds.VerticalResolutionFeedbackEventId:
case DMInputEventIds.FramesPerSecondFeedbackEventId:
case DMInputEventIds.ResolutionEventId:
{
Debug.Console(1, this, "Input {0} resolution updated", args.Number);
var inputPort =
InputPorts.Cast<RoutingInputPortWithVideoStatuses>()
.FirstOrDefault((ip) => ip.Key.Contains(String.Format("inputCard{0}", args.Number)));
if (inputPort != null)
{
Debug.Console(1, this, "Updating resolution feedback for input {0}", args.Number);
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
}
break;
}
default: default:
{ {
Debug.Console(2, this, "DMInputChange fired for Input {0} with Unhandled EventId: {1}", args.Number, args.EventId); Debug.Console(2, this, "DMInputChange fired for Input {0} with Unhandled EventId: {1}", args.Number, args.EventId);
@@ -1050,7 +1156,7 @@ namespace PepperDash.Essentials.DM
var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis. var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis.
Outputs[output].VideoOutFeedback.Number; Outputs[output].VideoOutFeedback.Number;
Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, inputNumber, output); Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", Name, inputNumber, output);
if (VideoOutputFeedbacks.ContainsKey(output)) if (VideoOutputFeedbacks.ContainsKey(output))
{ {
@@ -1077,7 +1183,7 @@ namespace PepperDash.Essentials.DM
var inputNumber = Chassis.Outputs[output].AudioOutFeedback == null ? 0 : Chassis. var inputNumber = Chassis.Outputs[output].AudioOutFeedback == null ? 0 : Chassis.
Outputs[output].AudioOutFeedback.Number; Outputs[output].AudioOutFeedback.Number;
Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, inputNumber, output); Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name, inputNumber, output);
if (AudioOutputFeedbacks.ContainsKey(output)) if (AudioOutputFeedbacks.ContainsKey(output))
{ {
@@ -1388,6 +1494,16 @@ namespace PepperDash.Essentials.DM
{ {
trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1;
} }
var videoStatus = inputPort as RoutingInputPortWithVideoStatuses;
if (videoStatus == null)
{
return;
}
Debug.Console(1, this, "Linking {0} to join {1} for resolution feedback.", videoStatus.Key, joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin);
videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]);
} }
private void LinkStreamInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) private void LinkStreamInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin)
@@ -1428,6 +1544,13 @@ namespace PepperDash.Essentials.DM
InputStreamCardStateFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[join]); InputStreamCardStateFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[join]);
trilist.UShortInput[join].UShortValue = InputStreamCardStateFeedbacks[ioSlot].UShortValue; trilist.UShortInput[join].UShortValue = InputStreamCardStateFeedbacks[ioSlot].UShortValue;
var videoStatus = inputPort as RoutingInputPortWithVideoStatuses;
if (videoStatus != null)
{
videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]);
}
} }
private void LinkStreamOutputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) private void LinkStreamOutputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin)
@@ -1564,10 +1687,19 @@ namespace PepperDash.Essentials.DM
{ {
trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1;
} }
var videoStatus = inputPort as RoutingInputPortWithVideoStatuses;
if (videoStatus == null)
{
return;
}
Debug.Console(1, this, "Linking {0} to join {1} for resolution feedback.", videoStatus.Key, joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin);
videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]);
} }
private void LinkAdvancedTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, private void LinkAdvancedTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap,
uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter)
{ {
var transmitter = basicTransmitter as DmTxControllerBase; var transmitter = basicTransmitter as DmTxControllerBase;
if (transmitter == null) return; if (transmitter == null) return;
@@ -1581,7 +1713,9 @@ namespace PepperDash.Essentials.DM
if (txRoutingInputs == null) return; if (txRoutingInputs == null) return;
var inputPorts = txRoutingInputs.InputPorts.Where((p) => p.Port is EndpointHdmiInput || p.Port is EndpointDisplayPortInput).ToList(); var inputPorts =
txRoutingInputs.InputPorts.Where(
(p) => p.Port is EndpointHdmiInput || p.Port is EndpointDisplayPortInput).ToList();
if (inputPorts.Count == 0) if (inputPorts.Count == 0)
{ {
@@ -1614,6 +1748,19 @@ namespace PepperDash.Essentials.DM
trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue =
(ushort) transmitter.HdcpSupportCapability; (ushort) transmitter.HdcpSupportCapability;
var videoStatus =
InputPorts[string.Format("inputCard{0}--dmIn", ioSlot)] as RoutingInputPortWithVideoStatuses;
if (videoStatus == null)
{
return;
}
Debug.Console(1, this, "Linking {0} to join {1} for resolution feedback.", videoStatus.Key,
joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin);
videoStatus.VideoStatus.VideoResolutionFeedback.LinkInputSig(
trilist.StringInput[joinMap.InputCurrentResolution.JoinNumber + ioSlotJoin]);
} }
private void LinkTxOnlineFeedbackToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, private void LinkTxOnlineFeedbackToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap,
@@ -1896,15 +2043,15 @@ namespace PepperDash.Essentials.DM
{ {
var props = JsonConvert.DeserializeObject var props = JsonConvert.DeserializeObject
<PepperDash.Essentials.DM.Config.DMChassisPropertiesConfig>(dc.Properties.ToString()); <DMChassisPropertiesConfig>(dc.Properties.ToString());
return PepperDash.Essentials.DM.DmChassisController. return DmChassisController.
GetDmChassisController(dc.Key, dc.Name, type, props); GetDmChassisController(dc.Key, dc.Name, type, props);
} }
else if (type.StartsWith("dmmd128x") || type.StartsWith("dmmd64x")) else if (type.StartsWith("dmmd128x") || type.StartsWith("dmmd64x"))
{ {
var props = JsonConvert.DeserializeObject var props = JsonConvert.DeserializeObject
<PepperDash.Essentials.DM.Config.DMChassisPropertiesConfig>(dc.Properties.ToString()); <DMChassisPropertiesConfig>(dc.Properties.ToString());
return PepperDash.Essentials.DM.DmBladeChassisController. return DmBladeChassisController.
GetDmChassisController(dc.Key, dc.Name, type, props); GetDmChassisController(dc.Key, dc.Name, type, props);
} }

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json; using Newtonsoft.Json;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
@@ -15,421 +16,489 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.DM.Chassis namespace PepperDash.Essentials.DM.Chassis
{ {
[Description("Wrapper class for all HdMdNxM4E switchers")] [Description("Wrapper class for all HdMdNxM4E switchers")]
public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback
{ {
private HdMdNxM _Chassis; private HdMdNxM _Chassis;
private HdMd4x14kE _Chassis4x1; private HdMd4x14kE _Chassis4x1;
//IroutingNumericEvent //IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange; public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
public Dictionary<uint, string> InputNames { get; set; } public Dictionary<uint, string> InputNames { get; set; }
public Dictionary<uint, string> OutputNames { get; set; } public Dictionary<uint, string> OutputNames { get; set; }
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; } public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; } public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
public FeedbackCollection<BoolFeedback> VideoInputSyncFeedbacks { get; private set; } public FeedbackCollection<BoolFeedback> VideoInputSyncFeedbacks { get; private set; }
public FeedbackCollection<IntFeedback> VideoOutputRouteFeedbacks { get; private set; } public FeedbackCollection<IntFeedback> VideoOutputRouteFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> InputNameFeedbacks { get; private set; } public FeedbackCollection<StringFeedback> InputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputNameFeedbacks { get; private set; } public FeedbackCollection<StringFeedback> OutputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputRouteNameFeedbacks { get; private set; } public FeedbackCollection<StringFeedback> OutputRouteNameFeedbacks { get; private set; }
public FeedbackCollection<BoolFeedback> InputHdcpEnableFeedback { get; private set; } public FeedbackCollection<BoolFeedback> InputHdcpEnableFeedback { get; private set; }
public FeedbackCollection<StringFeedback> DeviceNameFeedback { get; private set; } public StringFeedback DeviceNameFeedback { get; private set; }
public FeedbackCollection<BoolFeedback> AutoRouteFeedback { get; private set; } public BoolFeedback AutoRouteFeedback { get; private set; }
#region Constructor #region Constructor
public HdMdNxM4kEBridgeableController(string key, string name, HdMdNxM chassis, public HdMdNxM4kEBridgeableController(string key, string name, HdMdNxM chassis,
HdMdNxM4kEBridgeablePropertiesConfig props) HdMdNxM4kEBridgeablePropertiesConfig props)
: base(key, name, chassis) : base(key, name, chassis)
{ {
_Chassis = chassis; _Chassis = chassis;
var _props = props; Name = name;
InputNames = props.Inputs; if (props == null)
OutputNames = props.Outputs; {
Debug.Console(1, this, "HdMdNx4keBridgeableController properties are null, failed to build the device");
return;
}
VideoInputSyncFeedbacks = new FeedbackCollection<BoolFeedback>();
VideoOutputRouteFeedbacks = new FeedbackCollection<IntFeedback>();
InputNameFeedbacks = new FeedbackCollection<StringFeedback>();
OutputNameFeedbacks = new FeedbackCollection<StringFeedback>();
OutputRouteNameFeedbacks = new FeedbackCollection<StringFeedback>();
InputHdcpEnableFeedback = new FeedbackCollection<BoolFeedback>();
DeviceNameFeedback = new FeedbackCollection<StringFeedback>();
AutoRouteFeedback = new FeedbackCollection<BoolFeedback>();
InputPorts = new RoutingPortCollection<RoutingInputPort>(); if (props.Inputs != null)
OutputPorts = new RoutingPortCollection<RoutingOutputPort>(); {
foreach (var kvp in props.Inputs)
{
Debug.Console(1, this, "props.Inputs: {0}-{1}", kvp.Key, kvp.Value);
}
InputNames = props.Inputs;
}
if (props.Outputs != null)
{
foreach (var kvp in props.Outputs)
{
Debug.Console(1, this, "props.Outputs: {0}-{1}", kvp.Key, kvp.Value);
}
OutputNames = props.Outputs;
}
DeviceNameFeedback.Add(new StringFeedback(this.Name, () => this.Name)); DeviceNameFeedback = new StringFeedback(()=>Name);
if (_Chassis.NumberOfInputs == 1) VideoInputSyncFeedbacks = new FeedbackCollection<BoolFeedback>();
{ VideoOutputRouteFeedbacks = new FeedbackCollection<IntFeedback>();
_Chassis4x1 = _Chassis as HdMd4x14kE; InputNameFeedbacks = new FeedbackCollection<StringFeedback>();
AutoRouteFeedback.Add(new BoolFeedback(this.Name + "-" + InputNames[1], () => _Chassis4x1.AutoModeOnFeedback.BoolValue)); OutputNameFeedbacks = new FeedbackCollection<StringFeedback>();
} OutputRouteNameFeedbacks = new FeedbackCollection<StringFeedback>();
InputHdcpEnableFeedback = new FeedbackCollection<BoolFeedback>();
InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) if (_Chassis.NumberOfInputs == 1)
{ {
var index = i; _Chassis4x1 = _Chassis as HdMd4x14kE;
var inputName = InputNames[index]; AutoRouteFeedback = new BoolFeedback(() => _Chassis4x1.AutoModeOnFeedback.BoolValue);
_Chassis.Inputs[index].Name.StringValue = inputName; }
InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo, for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
eRoutingPortConnectionType.Hdmi, index, this) {
{ var index = i;
FeedbackMatchObject = _Chassis.HdmiInputs[index] var inputName = InputNames[index];
}); //_Chassis.Inputs[index].Name.StringValue = inputName;
VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue)); _Chassis.HdmiInputs[index].Name.StringValue = inputName;
InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].Name.StringValue));
InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[index].HdmiInputPort.HdcpSupportOnFeedback.BoolValue));
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo,
{ eRoutingPortConnectionType.Hdmi, _Chassis.HdmiInputs[index], this)
var index = i; {
var outputName = OutputNames[index]; FeedbackMatchObject = _Chassis.HdmiInputs[index]
_Chassis.Outputs[i].Name.StringValue = outputName; });
VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue));
//InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].NameFeedback.StringValue));
InputNameFeedbacks.Add(new StringFeedback(inputName, () => InputNames[index]));
InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[index].HdmiInputPort.HdcpSupportOnFeedback.BoolValue));
}
OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo, for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
eRoutingPortConnectionType.Hdmi, index, this) {
{ var index = i;
FeedbackMatchObject = _Chassis.HdmiOutputs[index] var outputName = OutputNames[index];
}); //_Chassis.Outputs[index].Name.StringValue = outputName;
VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[index].VideoOutFeedback.Number)); //_Chassis.HdmiOutputs[index].Name.StringValue = outputName;
OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].Name.StringValue));
OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue));
}
_Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange); OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo,
_Chassis.DMOutputChange += new DMOutputEventHandler(Chassis_DMOutputChange); eRoutingPortConnectionType.Hdmi, _Chassis.HdmiOutputs[index], this)
{
FeedbackMatchObject = _Chassis.HdmiOutputs[index]
});
VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback == null ? 0 : (int)_Chassis.Outputs[index].VideoOutFeedback.Number));
OutputNameFeedbacks.Add(new StringFeedback(outputName, () => OutputNames[index]));
OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue));
}
AddPostActivationAction(AddFeedbackCollections); _Chassis.DMInputChange += Chassis_DMInputChange;
} _Chassis.DMOutputChange += Chassis_DMOutputChange;
#endregion AddPostActivationAction(AddFeedbackCollections);
}
#region Methods #endregion
/// <summary> #region Methods
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
public void EnableHdcp(uint port) /// <summary>
{ /// Raise an event when the status of a switch object changes.
if (port > _Chassis.NumberOfInputs) return; /// </summary>
if (port <= 0) return; /// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOn(); public void EnableHdcp(uint port)
InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); {
} if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
public void DisableHdcp(uint port) _Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOn();
{ InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
if (port > _Chassis.NumberOfInputs) return; }
if (port <= 0) return;
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOff(); public void DisableHdcp(uint port)
InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); {
} if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
public void EnableAutoRoute() _Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOff();
{ InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
if (_Chassis.NumberOfInputs != 1) return; }
if (_Chassis4x1 == null) return; public void EnableAutoRoute()
{
if (_Chassis.NumberOfInputs != 1) return;
_Chassis4x1.AutoModeOn(); if (_Chassis4x1 == null) return;
}
public void DisableAutoRoute() _Chassis4x1.AutoModeOn();
{ }
if (_Chassis.NumberOfInputs != 1) return;
if (_Chassis4x1 == null) return; public void DisableAutoRoute()
{
if (_Chassis.NumberOfInputs != 1) return;
_Chassis4x1.AutoModeOff(); if (_Chassis4x1 == null) return;
}
#region PostActivate _Chassis4x1.AutoModeOff();
}
public void AddFeedbackCollections() #region PostActivate
{
AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback);
AddCollectionsToList(VideoOutputRouteFeedbacks);
AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks, DeviceNameFeedback);
}
#endregion public void AddFeedbackCollections()
{
AddFeedbackToList(DeviceNameFeedback);
AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback);
AddCollectionsToList(VideoOutputRouteFeedbacks);
AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks);
}
#region FeedbackCollection Methods #endregion
//Add arrays of collections #region FeedbackCollection Methods
public void AddCollectionsToList(params FeedbackCollection<BoolFeedback>[] newFbs)
{
foreach (FeedbackCollection<BoolFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
public void AddCollectionsToList(params FeedbackCollection<IntFeedback>[] newFbs)
{
foreach (FeedbackCollection<IntFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
public void AddCollectionsToList(params FeedbackCollection<StringFeedback>[] newFbs) //Add arrays of collections
{ public void AddCollectionsToList(params FeedbackCollection<BoolFeedback>[] newFbs)
foreach (FeedbackCollection<StringFeedback> fbCollection in newFbs) {
{ foreach (FeedbackCollection<BoolFeedback> fbCollection in newFbs)
foreach (var item in newFbs) {
{ foreach (var item in newFbs)
AddCollectionToList(item); {
} AddCollectionToList(item);
} }
} }
}
public void AddCollectionsToList(params FeedbackCollection<IntFeedback>[] newFbs)
{
foreach (FeedbackCollection<IntFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
//Add Collections public void AddCollectionsToList(params FeedbackCollection<StringFeedback>[] newFbs)
public void AddCollectionToList(FeedbackCollection<BoolFeedback> newFbs) {
{ foreach (FeedbackCollection<StringFeedback> fbCollection in newFbs)
foreach (var f in newFbs) {
{ foreach (var item in newFbs)
if (f == null) continue; {
AddCollectionToList(item);
}
}
}
AddFeedbackToList(f); //Add Collections
} public void AddCollectionToList(FeedbackCollection<BoolFeedback> newFbs)
} {
foreach (var f in newFbs)
{
if (f == null) continue;
public void AddCollectionToList(FeedbackCollection<IntFeedback> newFbs) AddFeedbackToList(f);
{ }
foreach (var f in newFbs) }
{
if (f == null) continue;
AddFeedbackToList(f); public void AddCollectionToList(FeedbackCollection<IntFeedback> newFbs)
} {
} foreach (var f in newFbs)
{
if (f == null) continue;
public void AddCollectionToList(FeedbackCollection<StringFeedback> newFbs) AddFeedbackToList(f);
{ }
foreach (var f in newFbs) }
{
if (f == null) continue;
AddFeedbackToList(f); public void AddCollectionToList(FeedbackCollection<StringFeedback> newFbs)
} {
} foreach (var f in newFbs)
{
if (f == null) continue;
//Add Individual Feedbacks AddFeedbackToList(f);
public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback newFb) }
{ }
if (newFb == null) return;
if (!Feedbacks.Contains(newFb)) //Add Individual Feedbacks
{ public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback newFb)
Feedbacks.Add(newFb); {
} if (newFb == null) return;
}
#endregion if (!Feedbacks.Contains(newFb))
{
Feedbacks.Add(newFb);
}
}
#region IRouting Members #endregion
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) #region IRouting Members
{
// Try to make switch only when necessary. The unit appears to toggle when already selected.
var current = _Chassis.HdmiOutputs[(uint)outputSelector].VideoOut;
if (current != _Chassis.HdmiInputs[(uint)inputSelector])
_Chassis.HdmiOutputs[(uint)outputSelector].VideoOut = _Chassis.HdmiInputs[(uint)inputSelector];
}
#endregion public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
{
var input = inputSelector as HdMdNxMHdmiInput; //changed from HdMdNxM4kzEHdmiInput;
var output = outputSelector as HdMdNxMHdmiOutput;
Debug.Console(2, this, "ExecuteSwitch: input={0} output={1}", input, output);
#region IRoutingNumeric Members if (output == null)
{
Debug.Console(0, this, "Unable to make switch. output selector is not HdMdNxMHdmiOutput");
return;
}
public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) // Try to make switch only when necessary. The unit appears to toggle when already selected.
{ var current = output.VideoOut;
ExecuteSwitch(inputSelector, outputSelector, signalType); if (current != input)
} output.VideoOut = input;
}
#endregion #endregion
#endregion #region IRoutingNumeric Members
#region Bridge Linking public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType)
{
var input = inputSelector == 0 ? null : _Chassis.HdmiInputs[inputSelector];
var output = _Chassis.HdmiOutputs[outputSelector];
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) Debug.Console(2, this, "ExecuteNumericSwitch: input={0} output={1}", input, output);
{
var joinMap = new HdMdNxM4kEControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); ExecuteSwitch(input, output, signalType);
}
if (!string.IsNullOrEmpty(joinMapSerialized)) #endregion
joinMap = JsonConvert.DeserializeObject<HdMdNxM4kEControllerJoinMap>(joinMapSerialized);
if (bridge != null) #endregion
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); #region Bridge Linking
DeviceNameFeedback[this.Name].LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]);
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new HdMdNxM4kEControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<HdMdNxM4kEControllerJoinMap>(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.");
}
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
DeviceNameFeedback.LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]);
if (_Chassis4x1 != null)
{
trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOn());
trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOff());
AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]);
}
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
var joinIndex = i - 1;
var input = i;
//Digital
VideoInputSyncFeedbacks[InputNames[input]].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + joinIndex]);
InputHdcpEnableFeedback[InputNames[input]].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + joinIndex]);
InputHdcpEnableFeedback[InputNames[input]].LinkComplementInputSig(trilist.BooleanInput[joinMap.DisableInputHdcp.JoinNumber + joinIndex]);
trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + joinIndex, () => EnableHdcp(input));
trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + joinIndex, () => DisableHdcp(input));
//Serial
InputNameFeedbacks[InputNames[input]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]);
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
var joinIndex = i - 1;
var output = i;
//Analog
VideoOutputRouteFeedbacks[OutputNames[output]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]);
trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteNumericSwitch(a, (ushort) output, eRoutingSignalType.AudioVideo));
//Serial
OutputNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]);
OutputRouteNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]);
}
_Chassis.OnlineStatusChange += Chassis_OnlineStatusChange;
trilist.OnlineStatusChange += (d, args) =>
{
if (!args.DeviceOnLine) return;
// feedback updates was moved to the Chassis_OnlineStatusChange
// due to the amount of time it takes for the device to come online
};
}
#endregion
#region Events
void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args)
{
IsOnline.FireUpdate();
if (!args.DeviceOnLine) return;
foreach (var feedback in Feedbacks)
{
feedback.FireUpdate();
}
if (_Chassis4x1 != null) if (_Chassis4x1 != null)
{ AutoRouteFeedback.FireUpdate();
trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOn()); }
trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOff());
AutoRouteFeedback[this.Name + "-" + InputNames[1]].LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]);
}
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++) void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
{ {
var joinIndex = i - 1; if (args.EventId != DMOutputEventIds.VideoOutEventId) return;
//Digital
VideoInputSyncFeedbacks[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + joinIndex]);
InputHdcpEnableFeedback[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + joinIndex]);
InputHdcpEnableFeedback[InputNames[i]].LinkComplementInputSig(trilist.BooleanInput[joinMap.DisableInputHdcp.JoinNumber + joinIndex]);
trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + joinIndex, () => EnableHdcp(i));
trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + joinIndex, () => DisableHdcp(i));
//Serial var output = args.Number;
InputNameFeedbacks[InputNames[i]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]);
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++) var inputNumber = _Chassis.HdmiOutputs[output].VideoOutFeedback == null
{ ? 0
var joinIndex = i - 1; : _Chassis.HdmiOutputs[output].VideoOutFeedback.Number;
//Analog
VideoOutputRouteFeedbacks[OutputNames[i]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]);
trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteSwitch(a, i, eRoutingSignalType.AudioVideo));
//Serial var outputName = OutputNames[output];
OutputNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]);
OutputRouteNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]);
}
_Chassis.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler(Chassis_OnlineStatusChange); var feedback = VideoOutputRouteFeedbacks[outputName];
trilist.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler((d, args) => if (feedback == null)
{ {
if (args.DeviceOnLine) return;
{ }
foreach (var feedback in Feedbacks) var inPort =
InputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.HdmiOutputs[output].VideoOutFeedback);
var outPort = OutputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.HdmiOutputs[output]);
feedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(output, inputNumber, outPort, inPort, eRoutingSignalType.AudioVideo));
}
void Chassis_DMInputChange(Switch device, DMInputEventArgs args)
{
switch (args.EventId)
{
case DMInputEventIds.VideoDetectedEventId:
{
Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", args.EventId);
foreach (var item in VideoInputSyncFeedbacks)
{ {
feedback.FireUpdate(); item.FireUpdate();
} }
} break;
}); }
} case DMInputEventIds.InputNameFeedbackEventId:
case DMInputEventIds.InputNameEventId:
case DMInputEventIds.NameFeedbackEventId:
{
Debug.Console(1, this, "Event ID {0}: Updating name feedbacks.", args.EventId);
Debug.Console(1, this, "Input {0} Name {1}", args.Number,
_Chassis.HdmiInputs[args.Number].NameFeedback.StringValue);
foreach (var item in InputNameFeedbacks)
{
item.FireUpdate();
}
break;
}
default:
{
Debug.Console(1, this, "Unhandled DM Input Event ID {0}", args.EventId);
break;
}
}
}
#endregion
#region Factory
public class HdMdNxM4kEControllerFactory : EssentialsDeviceFactory<HdMdNxM4kEBridgeableController>
{
public HdMdNxM4kEControllerFactory()
{
TypeNames = new List<string>() { "hdmd4x14ke-bridgeable", "hdmd4x24ke", "hdmd6x24ke" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new HD-MD-NxM-4K-E Device");
var props = JsonConvert.DeserializeObject<HdMdNxM4kEBridgeablePropertiesConfig>(dc.Properties.ToString());
var type = dc.Type.ToLower();
var control = props.Control;
var ipid = control.IpIdInt;
var address = control.TcpSshProperties.Address;
switch (type)
{
case ("hdmd4x14ke-bridgeable"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x14kE(ipid, address, Global.ControlSystem), props);
case ("hdmd4x24ke"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x24kE(ipid, address, Global.ControlSystem), props);
case ("hdmd6x24ke"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd6x24kE(ipid, address, Global.ControlSystem), props);
default:
return null;
}
}
}
#endregion
#endregion
#region Events }
void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args)
{
if (!args.DeviceOnLine) return;
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
_Chassis.Inputs[i].Name.StringValue = InputNames[i];
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
_Chassis.Outputs[i].Name.StringValue = OutputNames[i];
}
foreach (var feedback in Feedbacks)
{
feedback.FireUpdate();
}
}
void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
{
if (args.EventId != DMOutputEventIds.VideoOutEventId) return;
for (var i = 0; i < VideoOutputRouteFeedbacks.Count; i++)
{
var index = i;
var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1].VideoOutFeedback);
var localOutputPort =
OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1]);
VideoOutputRouteFeedbacks[i].FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs((ushort)i, VideoOutputRouteFeedbacks[i].UShortValue, localOutputPort, localInputPort, eRoutingSignalType.AudioVideo));
}
}
void Chassis_DMInputChange(Switch device, DMInputEventArgs args)
{
if (args.EventId != DMInputEventIds.VideoDetectedEventId) return;
foreach (var item in VideoInputSyncFeedbacks)
{
item.FireUpdate();
}
}
#endregion
#region Factory
public class HdMdNxM4kEControllerFactory : EssentialsDeviceFactory<HdMdNxM4kEBridgeableController>
{
public HdMdNxM4kEControllerFactory()
{
TypeNames = new List<string>() { "hdmd4x14ke-bridgeable", "hdmd4x24ke", "hdmd6x24ke" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new HD-MD-NxM-4K-E Device");
var props = JsonConvert.DeserializeObject<HdMdNxM4kEBridgeablePropertiesConfig>(dc.Properties.ToString());
var type = dc.Type.ToLower();
var control = props.Control;
var ipid = control.IpIdInt;
var address = control.TcpSshProperties.Address;
switch (type)
{
case ("hdmd4x14ke-bridgeable"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x14kE(ipid, address, Global.ControlSystem), props);
case ("hdmd4x24ke"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x24kE(ipid, address, Global.ControlSystem), props);
case ("hdmd6x24ke"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd6x24kE(ipid, address, Global.ControlSystem), props);
default:
return null;
}
}
}
#endregion
}
} }

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DM; using Crestron.SimplSharpPro.DM;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -13,6 +14,7 @@ using PepperDash.Essentials.DM.Config;
namespace PepperDash.Essentials.DM.Chassis namespace PepperDash.Essentials.DM.Chassis
{ {
[Obsolete("Please use HdMdNxM4kEBridgeable Controller")]
public class HdMdNxM4kEController : CrestronGenericBaseDevice, IRoutingInputsOutputs, IRouting public class HdMdNxM4kEController : CrestronGenericBaseDevice, IRoutingInputsOutputs, IRouting
{ {
public HdMdNxM Chassis { get; private set; } public HdMdNxM Chassis { get; private set; }
@@ -31,6 +33,7 @@ namespace PepperDash.Essentials.DM.Chassis
HdMdNxM4kEPropertiesConfig props) HdMdNxM4kEPropertiesConfig props)
: base(key, name, chassis) : base(key, name, chassis)
{ {
Debug.Console(0, this, "Type hdmd4x14ke is obsolete. Please use hdmd4x14ke-bridgeable");
Chassis = chassis; Chassis = chassis;
// logical ports // logical ports
@@ -43,14 +46,19 @@ namespace PepperDash.Essentials.DM.Chassis
OutputPorts = new RoutingPortCollection<RoutingOutputPort>(); OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
OutputPorts.Add(new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, OutputPorts.Add(new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this)); eRoutingPortConnectionType.Hdmi, null, this));
// physical settings // physical settings
if (props != null && props.Inputs != null) if (props != null && props.Inputs != null)
{ {
var inputRegex = new Regex(@"(?<InputNum>\d)", RegexOptions.IgnoreCase);
foreach (var kvp in props.Inputs) foreach (var kvp in props.Inputs)
{ {
// strip "hdmiIn" // get numnbers from key and convert to int
var inputNum = Convert.ToUInt32(kvp.Key.Substring(6)); //var inputNum = Convert.ToUInt32(kvp.Key.Substring(6));
var inputMatch = inputRegex.Match(kvp.Key);
if (inputMatch == null) continue;
var inputNum = Convert.ToUInt32(inputMatch.Groups["InputNum"].Value);
var port = chassis.HdmiInputs[inputNum].HdmiInputPort; var port = chassis.HdmiInputs[inputNum].HdmiInputPort;
// set hdcp disables // set hdcp disables

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Describes a device that has Do Not Disturb mode capability
/// </summary>
public interface IHasDoNotDisturbMode
{
/// <summary>
/// Indictes whether Do Not Disturb mode is on (Activated)
/// </summary>
BoolFeedback DoNotDisturbModeIsOnFeedback { get; }
/// <summary>
/// Activates Do Not Disturb mode
/// </summary>
void ActivateDoNotDisturbMode();
/// <summary>
/// Deactivates Do Not Disturb mode
/// </summary>
void DeactivateDoNotDisturbMode();
/// <summary>
/// Toggles Do Not Disturb mode
/// </summary>
void ToggleDoNotDisturbMode();
}
public interface IHasDoNotDisturbModeWithTimeout : IHasDoNotDisturbMode
{
/// <summary>
/// Activates Do Not Disturb mode with a timeout
/// </summary>
/// <param name="timeout"></param>
void ActivateDoNotDisturbMode(int timeout);
}
}

View File

@@ -235,6 +235,15 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{ {
Calls = new List<Call>(); Calls = new List<Call>();
} }
#region Overrides of Object
public override string ToString()
{
return String.Format("{0}:{1}: {2}-{3}", Title, Agenda, StartTime, EndTime);
}
#endregion
} }
public class Call public class Call

View File

@@ -108,6 +108,7 @@
<Compile Include="Codec\eCodecCallStatus.cs" /> <Compile Include="Codec\eCodecCallStatus.cs" />
<Compile Include="Codec\eMeetingPrivacy.cs" /> <Compile Include="Codec\eMeetingPrivacy.cs" />
<Compile Include="Codec\iCodecAudio.cs" /> <Compile Include="Codec\iCodecAudio.cs" />
<Compile Include="Codec\IHasDoNotDisturb.cs" />
<Compile Include="Codec\IHasExternalSourceSwitching.cs" /> <Compile Include="Codec\IHasExternalSourceSwitching.cs" />
<Compile Include="ImageProcessors\TVOneCorio.cs" /> <Compile Include="ImageProcessors\TVOneCorio.cs" />
<Compile Include="ImageProcessors\TVOneCorioPropertiesConfig.cs" /> <Compile Include="ImageProcessors\TVOneCorioPropertiesConfig.cs" />
@@ -117,13 +118,16 @@
<Compile Include="ImageProcessors\AnalogWay\AnalogWayLiveCorePropertiesConfig.cs" /> <Compile Include="ImageProcessors\AnalogWay\AnalogWayLiveCorePropertiesConfig.cs" />
<Compile Include="SoftCodec\BlueJeansPc.cs" /> <Compile Include="SoftCodec\BlueJeansPc.cs" />
<Compile Include="VideoCodec\CiscoCodec\CiscoCamera.cs" /> <Compile Include="VideoCodec\CiscoCodec\CiscoCamera.cs" />
<Compile Include="VideoCodec\CiscoCodec\CiscoCodecJoinMap.cs" />
<Compile Include="VideoCodec\CiscoCodec\RoomPresets.cs" /> <Compile Include="VideoCodec\CiscoCodec\RoomPresets.cs" />
<Compile Include="Cameras\CameraControl.cs" /> <Compile Include="Cameras\CameraControl.cs" />
<Compile Include="Display\PanasonicThDisplay.cs" /> <Compile Include="Display\PanasonicThDisplay.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingInfo.cs" /> <Compile Include="VideoCodec\Interfaces\IHasMeetingInfo.cs" />
<Compile Include="VideoCodec\Interfaces\IHasParticipants.cs" /> <Compile Include="VideoCodec\Interfaces\IHasParticipants.cs" />
<Compile Include="VideoCodec\Interfaces\IHasPresentationOnlyMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" /> <Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewSize.cs" /> <Compile Include="VideoCodec\Interfaces\IHasSelfviewSize.cs" />
<Compile Include="VideoCodec\Interfaces\IHasStandbyMode.cs" />
<Compile Include="VideoCodec\Interfaces\IHasStartMeeting.cs" /> <Compile Include="VideoCodec\Interfaces\IHasStartMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\iVideoCodecInfo.cs" /> <Compile Include="VideoCodec\Interfaces\iVideoCodecInfo.cs" />
<Compile Include="Codec\iHasCallFavorites.cs" /> <Compile Include="Codec\iHasCallFavorites.cs" />

View File

@@ -0,0 +1,120 @@
using System;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges.JoinMaps;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
public class CiscoCodecJoinMap : VideoCodecControllerJoinMap
{
#region Digital
[JoinName("ActivateDoNotDisturbMode")]
public JoinDataComplete ActivateDoNotDisturbMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 221,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Activates Do Not Disturb Mode. FB High if active.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DeactivateDoNotDisturbMode")]
public JoinDataComplete DeactivateDoNotDisturbMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 222,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Deactivates Do Not Disturb Mode. FB High if deactivated.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ToggleDoNotDisturbMode")]
public JoinDataComplete ToggleDoNotDisturbMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 223,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Toggles Do Not Disturb Mode.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivateStandby")]
public JoinDataComplete ActivateStandby = new JoinDataComplete(
new JoinData
{
JoinNumber = 226,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Activates Standby Mode. FB High if active.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DeactivateStandby")]
public JoinDataComplete DeactivateStandby = new JoinDataComplete(
new JoinData
{
JoinNumber = 227,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Deactivates Standby Mode. FB High if deactivated.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivateHalfWakeMode")]
public JoinDataComplete ActivateHalfWakeMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 228,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Activates Half Wake Mode. FB High if active.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
#endregion
#region Analog
#endregion
#region Serials
#endregion
public CiscoCodecJoinMap(uint joinStart)
: base(joinStart, typeof(CiscoCodecJoinMap))
{
}
public CiscoCodecJoinMap(uint joinStart, Type type)
: base(joinStart, type)
{
}
}
}

View File

@@ -28,7 +28,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public class CiscoSparkCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory, public class CiscoSparkCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory,
IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView, IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView,
ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets, IHasExternalSourceSwitching, IHasBranding, IHasCameraOff, IHasCameraMute ICommunicationMonitor, IRouting, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets,
IHasExternalSourceSwitching, IHasBranding, IHasCameraOff, IHasCameraMute, IHasDoNotDisturbMode,
IHasHalfWakeMode
{ {
private bool _externalSourceChangeRequested; private bool _externalSourceChangeRequested;
@@ -316,6 +318,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CameraIsMutedFeedback = CameraIsOffFeedback; CameraIsMutedFeedback = CameraIsOffFeedback;
SupportsCameraOff = true; SupportsCameraOff = true;
DoNotDisturbModeIsOnFeedback = new BoolFeedback(() => CodecStatus.Status.Conference.DoNotDisturb.BoolValue);
HalfWakeModeIsOnFeedback = new BoolFeedback(() => CodecStatus.Status.Standby.State.Value == "Halfwake");
PresentationViewMaximizedFeedback = new BoolFeedback(() => CurrentPresentationView == "Maximized"); PresentationViewMaximizedFeedback = new BoolFeedback(() => CurrentPresentationView == "Maximized");
Communication = comm; Communication = comm;
@@ -413,7 +418,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CodecStatus.Status.Audio.Volume.ValueChangedAction = VolumeLevelFeedback.FireUpdate; CodecStatus.Status.Audio.Volume.ValueChangedAction = VolumeLevelFeedback.FireUpdate;
CodecStatus.Status.Audio.VolumeMute.ValueChangedAction = MuteFeedback.FireUpdate; CodecStatus.Status.Audio.VolumeMute.ValueChangedAction = MuteFeedback.FireUpdate;
CodecStatus.Status.Audio.Microphones.Mute.ValueChangedAction = PrivacyModeIsOnFeedback.FireUpdate; CodecStatus.Status.Audio.Microphones.Mute.ValueChangedAction = PrivacyModeIsOnFeedback.FireUpdate;
CodecStatus.Status.Standby.State.ValueChangedAction = StandbyIsOnFeedback.FireUpdate; CodecStatus.Status.Standby.State.ValueChangedAction = new Action(() =>
{
StandbyIsOnFeedback.FireUpdate();
HalfWakeModeIsOnFeedback.FireUpdate();
});
CodecStatus.Status.RoomAnalytics.PeoplePresence.ValueChangedAction = RoomIsOccupiedFeedback.FireUpdate; CodecStatus.Status.RoomAnalytics.PeoplePresence.ValueChangedAction = RoomIsOccupiedFeedback.FireUpdate;
CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate; CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate;
CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = CameraAutoModeIsOnFeedback.FireUpdate; CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = CameraAutoModeIsOnFeedback.FireUpdate;
@@ -423,6 +432,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout; CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout;
CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = SharingContentIsOnFeedback.FireUpdate; CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = SharingContentIsOnFeedback.FireUpdate;
CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = FarEndIsSharingContentFeedback.FireUpdate; CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = FarEndIsSharingContentFeedback.FireUpdate;
CodecStatus.Status.Conference.DoNotDisturb.ValueChangedAction = DoNotDisturbModeIsOnFeedback.FireUpdate;
try try
{ {
CodecStatus.Status.Video.Input.MainVideoMute.ValueChangedAction = CameraIsOffFeedback.FireUpdate; CodecStatus.Status.Video.Input.MainVideoMute.ValueChangedAction = CameraIsOffFeedback.FireUpdate;
@@ -575,6 +586,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
prefix + "/Status/Audio" + Delimiter + prefix + "/Status/Audio" + Delimiter +
prefix + "/Status/Call" + Delimiter + prefix + "/Status/Call" + Delimiter +
prefix + "/Status/Conference/Presentation" + Delimiter + prefix + "/Status/Conference/Presentation" + Delimiter +
prefix + "/Status/Conference/DoNotDisturb" + Delimiter +
prefix + "/Status/Cameras/SpeakerTrack" + Delimiter + prefix + "/Status/Cameras/SpeakerTrack" + Delimiter +
prefix + "/Status/RoomAnalytics" + Delimiter + prefix + "/Status/RoomAnalytics" + Delimiter +
prefix + "/Status/RoomPreset" + Delimiter + prefix + "/Status/RoomPreset" + Delimiter +
@@ -583,10 +595,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
prefix + "/Status/Video/Layout" + Delimiter + prefix + "/Status/Video/Layout" + Delimiter +
prefix + "/Status/Video/Input/MainVideoMute" + Delimiter + prefix + "/Status/Video/Input/MainVideoMute" + Delimiter +
prefix + "/Bookings" + Delimiter + prefix + "/Bookings" + Delimiter +
prefix + "/Event/CallDisconnect" + Delimiter +
prefix + "/Event/Bookings" + Delimiter + prefix + "/Event/Bookings" + Delimiter +
prefix + "/Event/CameraPresetListUpdated" + Delimiter + prefix + "/Event/CameraPresetListUpdated" + Delimiter +
prefix + "/Event/UserInterface/Presentation/ExternalSource/Selected/SourceIdentifier" + Delimiter; prefix + "/Event/UserInterface/Presentation/ExternalSource/Selected/SourceIdentifier" + Delimiter +
prefix + "/Event/CallDisconnect" + Delimiter; // Keep CallDisconnect last to detect when feedback registration completes correctly
} }
#endregion #endregion
@@ -1495,7 +1508,49 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{ {
var joinMap = new CiscoCodecJoinMap(joinStart);
var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey);
if (customJoins != null)
{
joinMap.SetCustomJoinData(customJoins);
}
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
LinkVideoCodecToApi(this, trilist, joinStart, joinMapKey, bridge); LinkVideoCodecToApi(this, trilist, joinStart, joinMapKey, bridge);
LinkCiscoCodecToApi(trilist, joinMap);
}
public void LinkCiscoCodecToApi(BasicTriList trilist, CiscoCodecJoinMap joinMap)
{
var dndCodec = this as IHasDoNotDisturbMode;
if (dndCodec != null)
{
dndCodec.DoNotDisturbModeIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.ActivateDoNotDisturbMode.JoinNumber]);
dndCodec.DoNotDisturbModeIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.DeactivateDoNotDisturbMode.JoinNumber]);
trilist.SetSigFalseAction(joinMap.ActivateDoNotDisturbMode.JoinNumber, () => dndCodec.ActivateDoNotDisturbMode());
trilist.SetSigFalseAction(joinMap.DeactivateDoNotDisturbMode.JoinNumber, () => dndCodec.DeactivateDoNotDisturbMode());
trilist.SetSigFalseAction(joinMap.ToggleDoNotDisturbMode.JoinNumber, () => dndCodec.ToggleDoNotDisturbMode());
}
var halfwakeCodec = this as IHasHalfWakeMode;
if (halfwakeCodec != null)
{
halfwakeCodec.StandbyIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.ActivateStandby.JoinNumber]);
halfwakeCodec.StandbyIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.DeactivateStandby.JoinNumber]);
halfwakeCodec.HalfWakeModeIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.ActivateHalfWakeMode.JoinNumber]);
trilist.SetSigFalseAction(joinMap.ActivateStandby.JoinNumber, () => halfwakeCodec.StandbyActivate());
trilist.SetSigFalseAction(joinMap.DeactivateStandby.JoinNumber, () => halfwakeCodec.StandbyDeactivate());
trilist.SetSigFalseAction(joinMap.ActivateHalfWakeMode.JoinNumber, () => halfwakeCodec.HalfwakeActivate());
}
} }
/// <summary> /// <summary>
@@ -2069,6 +2124,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
else else
CameraMuteOn(); CameraMuteOn();
} }
#region IHasDoNotDisturbMode Members
public BoolFeedback DoNotDisturbModeIsOnFeedback { get; private set; }
public void ActivateDoNotDisturbMode()
{
SendText("xCommand Conference DoNotDisturb Activate");
}
public void DeactivateDoNotDisturbMode()
{
SendText("xCommand Conference DoNotDisturb Deactivate");
}
public void ToggleDoNotDisturbMode()
{
if (DoNotDisturbModeIsOnFeedback.BoolValue)
{
DeactivateDoNotDisturbMode();
}
else
{
ActivateDoNotDisturbMode();
}
}
#endregion
#region IHasHalfWakeMode Members
public BoolFeedback HalfWakeModeIsOnFeedback { get; private set; }
public void HalfwakeActivate()
{
SendText("xCommand Standby Halfwake");
}
#endregion
} }

View File

@@ -440,9 +440,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public CallId CallId { get; set; } public CallId CallId { get; set; }
} }
public class DoNotDisturb public class DoNotDisturb : ValueProperty
{ {
public string Value { get; set; } string _Value;
public bool BoolValue { get; private set; }
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
// If the incoming value is "On" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "On" || value == "Active";
OnValueChanged();
}
}
} }
public class Mode public class Mode
@@ -600,6 +617,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Conference2() public Conference2()
{ {
Presentation = new Presentation(); Presentation = new Presentation();
DoNotDisturb = new DoNotDisturb();
} }
} }
@@ -1380,12 +1398,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public class State : ValueProperty public class State : ValueProperty
{ {
string _value;
public bool BoolValue { get; private set; } public bool BoolValue { get; private set; }
public string Value // Valid values are Standby/EnteringStandby/Halfwake/Off public string Value // Valid values are Standby/EnteringStandby/Halfwake/Off
{ {
get { return _value; }
set set
{ {
_value = value;
// If the incoming value is "On" it sets the BoolValue true, otherwise sets it false // If the incoming value is "On" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "On" || value == "Standby"; BoolValue = value == "On" || value == "Standby";
OnValueChanged(); OnValueChanged();
@@ -2091,6 +2113,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
Conference = new Conference2(); Conference = new Conference2();
SystemUnit = new SystemUnit(); SystemUnit = new SystemUnit();
Video = new Video(); Video = new Video();
Conference = new Conference2();
} }
} }

View File

@@ -36,8 +36,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
public string ShareStatus { get; private set; } public string ShareStatus { get; private set; }
[JsonProperty("isHost")] [JsonProperty("isHost")]
public Boolean IsHost { get; private set; } public Boolean IsHost { get; private set; }
[JsonProperty("isSharingMeeting")]
public Boolean IsSharingMeeting { get; private set; }
[JsonProperty("waitingForHost")]
public Boolean WaitingForHost { get; private set; }
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost) public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost)
{ {
Id = id; Id = id;
Name = name; Name = name;
@@ -45,6 +49,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
Password = password; Password = password;
ShareStatus = shareStatus; ShareStatus = shareStatus;
IsHost = isHost; IsHost = isHost;
IsSharingMeeting = isSharingMeeting;
WaitingForHost = waitingForHost;
} }
} }

View File

@@ -0,0 +1,18 @@
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
public interface IHasPresentationOnlyMeeting
{
void StartSharingOnlyMeeting();
void StartSharingOnlyMeeting(eSharingMeetingMode mode);
void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration);
void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration, string password);
void StartNormalMeetingFromSharingOnlyMeeting();
}
public enum eSharingMeetingMode
{
None,
Laptop,
Ios,
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
/// <summary>
/// Describes a device that has Standby Mode capability
/// </summary>
public interface IHasStandbyMode
{
BoolFeedback StandbyIsOnFeedback { get; }
void StandbyActivate();
void StandbyDeactivate();
}
/// <summary>
/// Describes a device that has Half Waek Mode capability
/// </summary>
public interface IHasHalfWakeMode : IHasStandbyMode
{
BoolFeedback HalfWakeModeIsOnFeedback { get; }
void HalfwakeActivate();
}
}

View File

@@ -25,7 +25,7 @@ using Feedback = PepperDash.Essentials.Core.Feedback;
namespace PepperDash.Essentials.Devices.Common.VideoCodec namespace PepperDash.Essentials.Devices.Common.VideoCodec
{ {
public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs, public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs,
IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced, IHasStandbyMode
{ {
private const int XSigEncoding = 28591; private const int XSigEncoding = 28591;
protected const int MaxParticipants = 50; protected const int MaxParticipants = 50;

View File

@@ -59,6 +59,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public List<zStatus.AudioVideoInputOutputLineItem> AudioOuputs { get; set; } public List<zStatus.AudioVideoInputOutputLineItem> AudioOuputs { get; set; }
public List<zStatus.AudioVideoInputOutputLineItem> Cameras { get; set; } public List<zStatus.AudioVideoInputOutputLineItem> Cameras { get; set; }
public zEvent.PhoneCallStatus PhoneCall { get; set; } public zEvent.PhoneCallStatus PhoneCall { get; set; }
public zEvent.NeedWaitForHost NeedWaitForHost { get; set; }
public ZoomRoomStatus() public ZoomRoomStatus()
{ {
@@ -76,6 +77,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
AudioOuputs = new List<zStatus.AudioVideoInputOutputLineItem>(); AudioOuputs = new List<zStatus.AudioVideoInputOutputLineItem>();
Cameras = new List<zStatus.AudioVideoInputOutputLineItem>(); Cameras = new List<zStatus.AudioVideoInputOutputLineItem>();
PhoneCall = new zEvent.PhoneCallStatus(); PhoneCall = new zEvent.PhoneCallStatus();
NeedWaitForHost = new zEvent.NeedWaitForHost();
} }
} }
@@ -756,6 +758,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// </summary> /// </summary>
public class zEvent public class zEvent
{ {
public class StartLocalPresentMeeting
{
public bool Success { get; set; }
}
public class NeedWaitForHost public class NeedWaitForHost
{ {
public bool Wait { get; set; } public bool Wait { get; set; }
@@ -1471,6 +1477,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public static List<Participant> GetGenericParticipantListFromParticipantsResult( public static List<Participant> GetGenericParticipantListFromParticipantsResult(
List<ListParticipant> participants) List<ListParticipant> participants)
{ {
if (participants.Count == 0)
{
return new List<Participant>();
}
//return participants.Select(p => new Participant //return participants.Select(p => new Participant
// { // {
// UserId = p.UserId, // UserId = p.UserId,

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
@@ -25,7 +26,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
IRouting, IRouting,
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting
{ {
private const long MeetingRefreshTimer = 60000; private const long MeetingRefreshTimer = 60000;
public uint DefaultMeetingDurationMin { get; private set; } public uint DefaultMeetingDurationMin { get; private set; }
@@ -111,6 +112,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer); CodecSchedule = new CodecScheduleAwareness(MeetingRefreshTimer);
if (_props.MinutesBeforeMeetingStart > 0)
{
CodecSchedule.MeetingWarningMinutes = _props.MinutesBeforeMeetingStart;
}
ReceivingContent = new BoolFeedback(FarEndIsSharingContentFeedbackFunc); ReceivingContent = new BoolFeedback(FarEndIsSharingContentFeedbackFunc);
SelfviewPipPositionFeedback = new StringFeedback(SelfviewPipPositionFeedbackFunc); SelfviewPipPositionFeedback = new StringFeedback(SelfviewPipPositionFeedbackFunc);
@@ -464,18 +470,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void SetUpCallFeedbackActions() private void SetUpCallFeedbackActions()
{ {
Status.Call.Sharing.PropertyChanged += (o, a) => Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate;
{
if (a.PropertyName == "State")
{
SharingContentIsOnFeedback.FireUpdate();
ReceivingContent.FireUpdate();
// Update the share status of the meeting info
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself());
MeetingInfo = meetingInfo;
}
};
Status.Call.PropertyChanged += (o, a) => Status.Call.PropertyChanged += (o, a) =>
{ {
@@ -487,6 +482,39 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}; };
} }
private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a)
{
if (a.PropertyName != "State")
{
return;
}
SharingContentIsOnFeedback.FireUpdate();
ReceivingContent.FireUpdate();
try
{
// Update the share status of the meeting info
if (MeetingInfo == null)
{
var sharingStatus = GetSharingStatus();
MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false);
return;
}
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None",
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost);
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);
}
}
/// <summary> /// <summary>
/// Subscribes to the PropertyChanged events on the state objects and fires the corresponding feedbacks. /// Subscribes to the PropertyChanged events on the state objects and fires the corresponding feedbacks.
/// </summary> /// </summary>
@@ -626,8 +654,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
case "isDirectPresentationConnected": case "isDirectPresentationConnected":
case "isSharingBlackMagic": case "isSharingBlackMagic":
{ {
Debug.Console(2, this, "Updating sharing status: {0}", a.PropertyName);
SharingContentIsOnFeedback.FireUpdate();
if (MeetingInfo == null)
{
//Ignoring for now, as the CallInfo return will create the appropriate value
return;
}
// Update the share status of the meeting info // Update the share status of the meeting info
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself()); var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
break; break;
} }
@@ -1208,7 +1244,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Participants.CurrentParticipants = participants; Participants.CurrentParticipants = participants;
// Update the share status of the meeting info // Update the share status of the meeting info
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus, GetIsHostMyself()); var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus, GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
PrintCurrentCallParticipants(); PrintCurrentCallParticipants();
@@ -1403,15 +1439,40 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
case "needwaitforhost": case "needwaitforhost":
{ {
var needWait = Status.NeedWaitForHost = JsonConvert.DeserializeObject<zEvent.NeedWaitForHost>(responseObj.ToString());
JsonConvert.DeserializeObject<zEvent.NeedWaitForHost>(responseObj.ToString());
if (needWait.Wait) Debug.Console(1, this, "NeedWaitForHost: {0}", Status.NeedWaitForHost.Wait);
{
// TODO: notify user to wait for host
}
break; if (Status.NeedWaitForHost.Wait)
{
if (MeetingInfo == null)
{
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true);
UpdateCallStatus();
break;
}
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true);
UpdateCallStatus();
break;
}
if (MeetingInfo == null)
{
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, false);
break;
}
MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password,
GetSharingStatus(), GetIsHostMyself(), false, false);
break;
} }
case "openvideofailforhoststop": case "openvideofailforhoststop":
{ {
@@ -1487,6 +1548,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
break; break;
} }
case "startlocalpresentmeeting":
{
var result = JsonConvert.DeserializeObject<zEvent.StartLocalPresentMeeting>(responseObj.ToString());
if (result.Success)
{
MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost);
break;
}
break;
}
default: default:
{ {
break; break;
@@ -1604,7 +1677,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.Console(1, this, "Error Deserializing feedback: {0}", ex); Debug.Console(1, this, "Error Deserializing feedback: {0}", ex.Message);
Debug.Console(2, this, "{0}", ex);
if (ex.InnerException != null)
{
Debug.Console(1, this,"Error Deserializing feedback inner exception: {0}", ex.InnerException.Message);
Debug.Console(2, this, "{0}", ex.InnerException.StackTrace);
}
} }
} }
@@ -1664,8 +1744,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// </summary> /// </summary>
private void UpdateCallStatus() private void UpdateCallStatus()
{ {
Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", Debug.Console(1, this,
Status.Call != null ? Status.Call.Status.ToString() : "no call"); "[UpdateCallStatus] Current Call Status: {0} Active Call Count: {1} Need Wait For Host: {2}",
Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count, Status.NeedWaitForHost.Wait);
if (Status.Call != null) if (Status.Call != null)
{ {
@@ -1710,17 +1791,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Type = eCodecCallType.Video, Type = eCodecCallType.Video,
}; };
if (!String.IsNullOrEmpty(_lastDialedMeetingNumber))
{
_lastDialedMeetingNumber = String.Empty;
}
ActiveCalls.Add(newCall); ActiveCalls.Add(newCall);
//Debug.Console(1, this, "[UpdateCallStatus] IF w/ meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}",
//Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count);
OnCallStatusChange(newCall); OnCallStatusChange(newCall);
} } else if (String.IsNullOrEmpty(Status.Call.Info.meeting_id) && Status.NeedWaitForHost.Wait)
else
{ {
//Debug.Console(1, this, "[UpdateCallStatus] IF w/o meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}", var newCall = new CodecActiveCallItem
//Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); {
Name = "Waiting For Host",
Number = "Waiting For Host",
Id = "Waiting For Host",
Status = newStatus,
Type = eCodecCallType.Video,
};
if (!String.IsNullOrEmpty(_lastDialedMeetingNumber))
{
_lastDialedMeetingNumber = String.Empty;
}
ActiveCalls.Add(newCall);
OnCallStatusChange(newCall);
} }
} }
} }
@@ -1731,15 +1827,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
switch (callStatus) switch (callStatus)
{ {
case zStatus.eCallStatus.IN_MEETING: case zStatus.eCallStatus.IN_MEETING:
if (Status.NeedWaitForHost.Wait)
{
Status.NeedWaitForHost.Wait = false;
}
existingCall.Status = eCodecCallStatus.Connected; existingCall.Status = eCodecCallStatus.Connected;
break; break;
case zStatus.eCallStatus.NOT_IN_MEETING: case zStatus.eCallStatus.NOT_IN_MEETING:
if (Status.NeedWaitForHost.Wait)
{
Status.NeedWaitForHost.Wait = false;
}
existingCall.Status = eCodecCallStatus.Disconnected; existingCall.Status = eCodecCallStatus.Disconnected;
break; break;
} }
Debug.Console(1, this, "[UpdateCallStatus] ELSE ActiveCalls.Count == {1} - Current Call Status: {0}", Debug.Console(1, this, "[UpdateCallStatus] ELSE ActiveCalls.Count == {1} - Current Call Status: {0}",
Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count); Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count);
OnCallStatusChange(existingCall); OnCallStatusChange(existingCall);
} }
@@ -1778,8 +1883,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
protected override void OnCallStatusChange(CodecActiveCallItem item) protected override void OnCallStatusChange(CodecActiveCallItem item)
{ {
base.OnCallStatusChange(item);
if (item.Status == eCodecCallStatus.Connected) if (item.Status == eCodecCallStatus.Connected)
{ {
@@ -1794,10 +1897,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
host, host,
Status.Call.Info.meeting_password, Status.Call.Info.meeting_password,
GetSharingStatus(), GetSharingStatus(),
GetIsHostMyself() GetIsHostMyself(),
!String.Equals(Status.Call.Info.meeting_type,"NORMAL"),
false
); );
} }
base.OnCallStatusChange(item);
Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}",
Status.Call != null ? Status.Call.Status.ToString() : "no call"); Status.Call != null ? Status.Call.Status.ToString() : "no call");
@@ -1811,24 +1918,33 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
string sharingState = "None"; string sharingState = "None";
if (Status.Call.Sharing.State == zEvent.eSharingState.Receiving) try
{ {
sharingState = "Receiving Content"; if (Status.Call.Sharing.State == zEvent.eSharingState.Receiving)
} {
if (Status.Sharing.isAirHostClientConnected) sharingState = "Receiving Content";
{ }
sharingState = "Sharing AirPlay"; if (Status.Sharing.isAirHostClientConnected)
} {
if (Status.Sharing.isDirectPresentationConnected) sharingState = "Sharing AirPlay";
{ }
sharingState = "Sharing Laptop"; if (Status.Sharing.isDirectPresentationConnected)
} {
if (Status.Sharing.isSharingBlackMagic) sharingState = "Sharing Laptop";
{ }
sharingState = "Sharing HDMI Source"; if (Status.Sharing.isSharingBlackMagic)
} {
sharingState = "Sharing HDMI Source";
}
return sharingState; return sharingState;
}
catch (Exception e)
{
Debug.Console(1, this, "Exception getting sharing status: {0}", e.Message);
Debug.Console(2, this, "{0}", e.StackTrace);
return sharingState;
}
} }
/// <summary> /// <summary>
@@ -1837,15 +1953,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <returns></returns> /// <returns></returns>
private bool GetIsHostMyself() private bool GetIsHostMyself()
{ {
var host = Participants.Host; try
if(host == null)
{ {
Debug.Console(2, this, "Host is currently null"); if (Participants.CurrentParticipants.Count == 0)
{
Debug.Console(2, this, "No current participants");
return false;
}
var host = Participants.Host;
if(host == null)
{
Debug.Console(2, this, "Host is currently null");
return false;
}
Debug.Console(2, this, "Host is: '{0}' IsMyself?: {1}", host.Name, host.IsMyself);
return host.IsMyself;
}
catch (Exception e)
{
Debug.Console(1, "Exception getting isHost: {0}", e.Message);
Debug.Console(2, "{0}", e.StackTrace);
return false; return false;
} }
Debug.Console(2, this, "Host is: '{0}' IsMyself?: {1}", host.Name, host.IsMyself);
return host.IsMyself;
} }
public override void StartSharing() public override void StartSharing()
@@ -1858,7 +1989,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// </summary> /// </summary>
public override void StopSharing() public override void StopSharing()
{ {
SendText("zCommand Call Sharing Disconnect"); if (Status.Sharing.isSharingBlackMagic)
{
SendText("zCommand Call Sharing HDMI Stop");
}
else
{
SendText("zCommand Call Sharing Disconnect");
}
} }
public override void PrivacyModeOn() public override void PrivacyModeOn()
@@ -2144,11 +2282,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public override void Dial(Meeting meeting) public override void Dial(Meeting meeting)
{ {
Debug.Console(1, this, "Dialing meeting.Id: {0} Title: {1}", meeting.Id, meeting.Title); Debug.Console(1, this, "Dialing meeting.Id: {0} Title: {1}", meeting.Id, meeting.Title);
_lastDialedMeetingNumber = meeting.Id;
SendText(string.Format("zCommand Dial Start meetingNumber: {0}", meeting.Id)); SendText(string.Format("zCommand Dial Start meetingNumber: {0}", meeting.Id));
} }
public override void Dial(string number) public override void Dial(string number)
{ {
Debug.Console(2, this, "Dialing number: {0}", number);
_lastDialedMeetingNumber = number; _lastDialedMeetingNumber = number;
SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number)); SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number));
} }
@@ -2859,7 +2999,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
#endregion #endregion
}
#region Implementation of IHasPresentationOnlyMeeting
public void StartSharingOnlyMeeting()
{
StartSharingOnlyMeeting(eSharingMeetingMode.None, 30, String.Empty);
}
public void StartSharingOnlyMeeting(eSharingMeetingMode mode)
{
StartSharingOnlyMeeting(mode, 30, String.Empty);
}
public void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration)
{
StartSharingOnlyMeeting(mode, duration, String.Empty);
}
public void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration, string password)
{
SendText(String.Format("zCommand Dial Sharing Duration: {0} DisplayState: {1} Password: {2}", duration, mode, password));
}
public void StartNormalMeetingFromSharingOnlyMeeting()
{
Debug.Console(2, this, "Converting Sharing Meeting to Normal Meeting");
SendText("zCommand call sharing ToNormal");
}
#endregion
}
/// <summary> /// <summary>
/// Zoom Room specific info object /// Zoom Room specific info object

View File

@@ -25,5 +25,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
//This layout will be selected when a call is connected and no content is being shared //This layout will be selected when a call is connected and no content is being shared
public string DefaultCallLayout { get; set; } public string DefaultCallLayout { get; set; }
public int MinutesBeforeMeetingStart { get; set; }
} }
} }