Compare commits

...

104 Commits
1.9.2 ... 1.9.7

Author SHA1 Message Date
Neil Dorin
a8d0dfb327 Merge pull request #852 from PepperDash/hotfix/dm-usb-routing
Hotfix/dm usb routing
2021-10-27 10:39:17 -06:00
Andrew Welker
cef9e0a9a6 Update UsbOutput routing 2021-10-27 07:46:50 -06:00
Andrew Welker
16369e31cf fix USB routing 2021-10-27 07:46:50 -06:00
Andrew Welker
38959414ff Fix USB Routing issue 2021-10-27 07:46:50 -06:00
Neil Dorin
bc3247297e Merge pull request #846 from PepperDash/hotfix/zoom-meetings-simpl 2021-10-07 12:48:32 -06:00
Andrew Welker
f7bf728263 fix(Devices_Common): Clear meeting list and fire event if no meetings are scheduled 2021-10-07 09:48:02 -06:00
Neil Dorin
025bf7adfb Merge pull request #840 from PepperDash/hotfix/PD-Core-update-initialize
Implement Initialize Method & Update PD Core
2021-09-28 13:09:25 -06:00
Andrew Welker
a6430a7bfe chore: Update PD Core to 1.1.0 2021-09-28 11:05:05 -06:00
Andrew Welker
b71c83bac0 feat: Update some internal Essentials devices to use Initialize method 2021-09-28 10:56:25 -06:00
Andrew Welker
5940ec17c2 feat: Add method call to constructor for EssentialsDevice 2021-09-28 10:56:24 -06:00
Andrew Welker
10445508b2 feat: Update Essentials Device to call Initialize method 2021-09-28 10:56:24 -06:00
Andrew Welker
66ecf43508 chore: Update PD Core to 1.0.48 2021-09-28 10:56:23 -06:00
Andrew Welker
77c4272219 Merge pull request #834 from PepperDash/hotfix/hd-md-outputname
Hotfix/hd md outputname
2021-09-21 15:47:20 -06:00
Andrew Welker
d78a378859 Merge branch 'main' into hotfix/hd-md-outputname 2021-09-21 15:21:47 -06:00
Jason DeVito
eec4484f78 fix: updates to resolve issues with routing and feedbacks in the HdMdNxM4kEBridgeableController class. 2021-09-21 16:11:13 -05:00
Andrew Welker
49e82f107b fix(Essentials_DM): Updates to try and fix some exceptions 2021-09-21 12:06:22 -06:00
Neil Dorin
c5162fb94d Merge pull request #831 from PepperDash/hotfix/dm-resolution-issues
DM Input Resolution not reporting over bridge
2021-09-21 10:32:45 -06:00
Neil Dorin
63b9ffdd26 Merge branch 'main' into hotfix/dm-resolution-issues 2021-09-21 10:17:26 -06:00
Andrew Welker
2e76b6ba0a fix(DM): Fix issue with bad cast for IVideoAttributesBasic
Also updates to use the DM routing input port rather than the tx AnyVideoInput for the DM input resolutions
2021-09-21 09:40:51 -06:00
Andrew Welker
cad45c04cb fix: Add method to register for the correct event for resolution feedback
The resolution feedback change events don't appear to bubble up to the main DMInput change event. It appears to require subscribing to an event on the VideoAttributes class that the input contains.
2021-09-20 16:12:39 -06:00
Andrew Welker
70d63a9f99 chore: Mark non-bridgeable class obsolete
Also add a debug message to give the new type to use.
2021-09-20 15:52:40 -06:00
Andrew Welker
30f63eee03 fix: Remove reference to DMOutput name sig
the HD-MD series of switchers appears to not populate the Name sig of the DMOutput, leading to a NullSig exception when attempting to set output names. This is probably because those names can't be set on the device itself, but some experimentation with hardware may be required to determine that completely.
2021-09-20 15:52:40 -06:00
Jason DeVito
9f1c512909 Updates to HdMdNxM4kEController.cs to implement regex pattern in place of substring on input definitions. Updated HdMdNxM4kEBridgeableController.cs to handle exception when constructing the device. 2021-09-20 15:52:39 -06:00
Neil Dorin
0d6cd8d55d Merge pull request #822 from PepperDash/hotfix/ci-newtonsoft-issues
ci: Update scripts to remove Newtonsoft.Compact.json
2021-09-20 14:24:11 -06:00
Neil Dorin
8e64140651 Merge branch 'main' into hotfix/ci-newtonsoft-issues 2021-09-20 13:28:54 -06:00
Neil Dorin
0da35c8572 Merge pull request #827 from PepperDash/hotfix/zoom-updates
Hotfix/zoom updates
2021-09-20 13:26:18 -06:00
Andrew Welker
9f3a3f64a8 fix: Update share behavior for Zoom Room 2021-09-16 13:27:09 -06:00
Andrew Welker
fe01842523 fix: Multiple fixes
Update to poll meetings every 60 seconds
Add property to allow for adjusting when Join button appears
Refactor call connected event handler
Adjust text for header for sharing-only meeting
Add logic to handle waiting for host state
2021-09-16 07:15:26 -06:00
Andrew Welker
4ffea1c98f fix: Add step to allow meeting number to be sent when entering password 2021-09-13 08:43:24 -06:00
Andrew Welker
73e3b049d8 build: Update nuspec file for maximum PD Core version 2021-09-13 08:33:36 -06:00
Andrew Welker
0ae38dddfc ci: Update scripts to remove Newtonsoft.Compact.json 2021-09-11 14:01:07 -06:00
Andrew Welker
871894e248 fix: Fix issue with receiving sharing state
In some circumstances, the sharing state can be retrieved prior to participants or meeting info being populated. In those cases, Essentials is now creating an empty meeting object if one doesn't exist, and populating host info with None if no host has been indicated yet.
2021-09-10 20:25:21 -06:00
Andrew Welker
fa6cabe246 refactor(Essentials_DM): Add event IDS and some logging to get resolution feedback 2021-09-09 07:44:05 -06:00
Andrew Welker
db3d96d448 feat(Essentials_DM): Update DmInputEvent handler for input resolution feedback 2021-09-08 15:26:16 -06:00
Andrew Welker
a28a078c4f feat(Essentials_DM): Update all card creation methods to pass appropriate input 2021-09-08 15:25:43 -06:00
Andrew Welker
d00a31e3a6 feat(Essentials_DM): Add overloads for AddDmInCardPorts & AddHdmiInCardPorts 2021-09-08 14:17:24 -06:00
Andrew Welker
77134f0a30 feat:(Essentials_DM) Update AddInputPortWithDebug
Adding an `IVideoAttributesBasic` as a parameter for this method relatively easily allows us to get the reported input resolution when it changes.
2021-09-08 14:15:52 -06:00
Andrew Welker
93dfb8780b feat:(Essentials) Add doc info and meeting button text join 2021-09-07 18:13:18 -06:00
Andrew Welker
f791feb848 feat:(Essentials) Update UI functionality depending on Zoom Meeting type 2021-09-07 18:12:52 -06:00
Andrew Welker
44509dc5ae feat:(Essentials) Add IsSharingMeeting setting to MeetingInfo 2021-09-07 18:12:13 -06:00
Andrew Welker
2d0dcd7336 feat:(Essentials) Add StartLocalPresentMeeting class 2021-09-07 18:11:48 -06:00
Andrew Welker
c255ae1525 feat:(Essentials) Add IsSharingMeeting property 2021-09-07 18:11:14 -06:00
Andrew Welker
d50027cc82 feat:(Essentials) Add IHasPresentationOnlyMeeting interface 2021-09-07 17:33:53 -06:00
Andrew Welker
9b64b7b7f3 fix:(Essentials) Created MeetingInfo Object if it didn't previously exist 2021-09-07 11:40:27 -06:00
Andrew Welker
147e712a01 Merge pull request #816 from PepperDash/hotfix/glspartcn-enable-feedback
fix: Replaced SetSigTrueAction and SetSigFalseAction calling SetEnable state with a single SetBoolSigAction.
2021-09-02 07:36:38 -06:00
Jason DeVito
9a1b069e24 feat: Added debug statements to sensor set and sensitivity methods.
fix: Replaced SetSigTrueAction and SetSigFalseAction calling SetEnable state with a single SetBoolSigAction.
2021-09-02 08:21:37 -05:00
Andrew Welker
d8cd04b35f Merge pull request #813 from PepperDash/hotfix/zoom-meetnow-updates
Hotfix/zoom meetnow updates
2021-08-31 19:00:14 -06:00
Neil Dorin
8539a6b79c fix(essentials): minor fixes to UI oddities 2021-08-31 18:18:24 -06:00
Neil Dorin
adec25104c feat(essentials): Updates to UI to deal with sharing feedback with no external sources. Adds End/Leave meeting button logic on meeting info subpage 2021-08-31 16:40:04 -06:00
Neil Dorin
a54cd9e1df feat(essentials): minor syntax updates 2021-08-31 10:13:56 -06:00
Neil Dorin
8af7b4b1db feat(essentials): Adds IsHost property to MeetingInfo to determine if the room is the host 2021-08-30 17:48:37 -06:00
Neil Dorin
3edb0145d0 fix(essentials): Adds JsonProperty attributes to MeetingInfo properties for serialization 2021-08-30 15:00:13 -06:00
Neil Dorin
0a1af09830 fix(essentials): Disables dial feedback phone formatting if codec is IHasStartMeeting 2021-08-30 12:07:09 -06:00
Neil Dorin
532f3ba237 feat(essentails): #811 Adds IHasMeetingInfo, implements on ZoomRoom and updates UI drivers #812 2021-08-27 17:57:21 -06:00
Andrew Welker
e1d9a46284 Merge pull request #809 from PepperDash/hotfix/mockvc-fixes
fix(essentials): Minor fixes for MockVc to make behavior more consist…
2021-08-27 10:11:36 -06:00
Neil Dorin
bfd383dfc7 fix(essentials): Minor fixes for MockVc to make behavior more consistent with real hardware 2021-08-27 09:48:43 -06:00
Neil Dorin
8ab87af859 Merge pull request #807 from PepperDash/hotfix/4series-cultureinfo-for-time-formats-and-dm-4kz-fix 2021-08-26 17:52:07 -06:00
Neil Dorin
47035d8386 fix(essentials): Attempt to catch case where meeting popup may not be dismissed if the room is on and the meeting is no longer joinable 2021-08-26 17:38:49 -06:00
Neil Dorin
c84ec4c899 fix(essentials): #806 switches method to print times for consistent 12h format
fix(essentials): #806 Updates more uses of ToShortTimeString()

fix(essentials): #806 fixes for VideoCodecUIDriver

fix(essentials): #806 final fixes for time format
2021-08-26 17:20:04 -06:00
Neil Dorin
4444328600 fix(essentials): #804 #805 Updates to prevent attempting to access null AudioSourceFeedback property on 4kz TX models 2021-08-26 16:48:56 -06:00
Andrew Welker
0d3eb42495 Merge pull request #803 from PepperDash/hotfix/add-IPasswordPrompt
Hotfix/add i password prompt
2021-08-20 17:06:21 -06:00
Neil Dorin
540a00861c fix(essentials): Adds missing file in .csproj 2021-08-19 16:02:24 -06:00
Neil Dorin
0014dd7a14 feat(essentials): #801 Adds IHasStartMeeting interface and implments on ZoomRoom 2021-08-19 15:19:19 -06:00
Neil Dorin
f922b871a1 refactor(essentials): Switches from zoom specific contact class to generic InvitableDirectoryContact class 2021-08-19 14:57:00 -06:00
Neil Dorin
b2331fa1e5 feat(essentials): Adds IsInvitableContact property with getter to DirectoryContact 2021-08-19 14:14:14 -06:00
Neil Dorin
8bf4b0d568 fix(essentails): Increase phonebook list limit to 10000 2021-08-19 12:49:11 -06:00
Neil Dorin
621205e65c fix(essentials): Hides password prompt on successful call connection 2021-08-19 12:04:11 -06:00
Neil Dorin
62fcf3856f fix(essentials): Minor update to clear out previous password text when displaying password prompt 2021-08-19 09:37:21 -06:00
Neil Dorin
dad986414c feat(essentials): Updated EssentialsVideoCodecUIDriver to display password prompt when joining password protected meeting 2021-08-18 17:55:04 -06:00
Neil Dorin
f298b5cc41 feat(essentials): Implements IPasswordPrompt on ZoomRoom 2021-08-18 14:45:16 -06:00
Neil Dorin
f8129fe7ae feat(essentials): #800 adds public access modifier on properties 2021-08-18 13:35:48 -06:00
Neil Dorin
dbdaedcca3 feat(essentials): #800 Adds IPasswordPrompt 2021-08-18 13:25:26 -06:00
Neil Dorin
893950d8c4 Merge pull request #798 from PepperDash/hotfix/room-method-updates 2021-08-18 08:30:53 -06:00
Andrew Welker
b780351bf0 Merge branch 'main' into hotfix/room-method-updates 2021-08-18 07:38:11 -06:00
Andrew Welker
6a1671aae1 ci: Remove PR trigger 2021-08-17 22:25:18 -06:00
Andrew Welker
9a1a23c88a fix: Instantiate Availability class when 2021-08-17 22:23:41 -06:00
Andrew Welker
2e4bb7466c Merge pull request #794 from PepperDash/hotfix/sg-ui-issue
fix(essentials): #792 refactors logic to show/hide SelectASourceVisible subpage
2021-08-17 21:48:50 -06:00
Neil Dorin
36a41ac477 fix(essentials): #792 refactors logic to show/hide SelectASourceVisible subpage 2021-08-17 18:00:41 -06:00
Andrew Welker
92f4d37cd6 refactor: Clean up Room Interfaces to help with ambiguities 2021-08-17 16:54:02 -06:00
Andrew Welker
b9479bab70 refactor: Rename Initialize to InitializeRoom 2021-08-17 16:54:01 -06:00
Andrew Welker
fd94a94ee9 Merge pull request #789 from PepperDash/hotfix/zoomroom-duplicate-participant-in-list
Hotfix/zoomroom duplicate participant in list
2021-08-17 16:26:18 -06:00
Jason DeVito
3fa2954ca0 style: Updated formatting for ZoomRoom.cs and IHasParticipants.cs 2021-08-17 16:46:24 -05:00
Jason DeVito
c4f6afa412 Fixed debug references used for call status that were printing Status.Call.Sharing.State. Added GetCurrentCallParticipants method to referesh participant list. Updated UpdateCallStatus to resolve issue with duplicate participants when admitted from the waiting room. 2021-08-17 15:56:57 -05:00
Jason DeVito
6bdda5451b Updated UpdateCallStatus method to fix call status references previously looking at Status.Call.Sharing.State. Added else statement to 'if(ActiveCalls.Count == 0)' used to cleanup after calls that refreshs the participant list. Added GetCurrentCallParticipant method used to poll the participant list. 2021-08-17 15:14:02 -05:00
Andrew Welker
3ee8c07ecd Merge pull request #786 from PepperDash/hotfix/IMobileControl3
feat(essentials): Adds IMobileControl3 interface to maintain backwards compatibility
2021-08-16 15:06:00 -06:00
Neil Dorin
01b713e6e1 feat(essentials): Adds IMobileControl3 interface to maintain backwards compatibility 2021-08-16 14:27:28 -06:00
Neil Dorin
ffd0fbc57b Merge pull request #783 from PepperDash/hotfix/UI-codec-directory-fixes
refactor: Add RefreshDirectory overload
2021-08-16 11:47:52 -06:00
Andrew Welker
23e8280904 refactor: Add RefreshDirectory overload
This allows the directory to be refreshed by the event that updates the directory correctly
2021-08-16 09:42:11 -06:00
Andrew Welker
6708be0d15 Merge pull request #779 from PepperDash/hotfix/zoomroom-fixes
Hotfix/zoomroom fixes
2021-08-16 08:22:19 -06:00
Jason DeVito
d193de79da Added GetSelfViewMode method to ZoomRoom.cs, upated Removed if statement in HideConfSelfVideo property that was blocking feedback updates and setting of the property from boot. Tested with Zoom Rooms system on site and verified working. Closes #781. 2021-08-16 08:26:27 -05:00
Neil Dorin
87ab43c745 fix(essentials): Updates to resolve oddities with ZoomRoom directory browsing and dialing 2021-08-13 13:45:46 -06:00
Neil Dorin
2a37e44d7d fix(essentials): fixes inverted activity call button state 2021-08-12 15:33:17 -06:00
Neil Dorin
efa801137c fix(Essentials): moves code inside null check for CurrentRoom 2021-08-12 14:53:41 -06:00
Neil Dorin
4b4f1f3c3d fix(essentials): Updates to staging subpage join logic 2021-08-12 14:48:19 -06:00
Neil Dorin
6e7bf061cf fix(essentials): Add null check for CurrentRoom 2021-08-12 13:51:48 -06:00
Neil Dorin
7f6160eb44 fix(essentials): Updates to better set feedback for current mode 2021-08-12 12:24:23 -06:00
Andrew Welker
b5004d5b1d Merge pull request #774 from PepperDash/hotfix/zoom-camera-fixes
Hotfix/zoom camera fixes
2021-08-11 11:46:42 -06:00
Neil Dorin
cea1d2fcdd Updates to mute toggle for ZoomRoom 2021-08-09 16:20:55 -06:00
Neil Dorin
22aea3089d #773 Adds some debug and sets the Capabilities value on ZoomRoomCamera
Also updates RunRouteAction in EssentialsHuddleVtc1Room to still call down in to main RunRouteAction method if called with a sourceListKey
2021-08-09 14:41:31 -06:00
Andrew Welker
43256acfcd Merge pull request #771 from PepperDash/hotfix/zoomroom-updates
Hotfix/zoomroom updates
2021-08-02 17:36:28 -06:00
Neil Dorin
1696ef3ac1 Adds LocalLayoutToggle() implementation and minor updates to UI Driver 2021-08-02 16:58:32 -06:00
Neil Dorin
19cbe480a6 reverts IMobileControl back to using EssentialsRoomBase instead of IEssentialsRoom for now 2021-07-29 16:39:34 -06:00
Neil Dorin
49c1c61a88 updates ZoomRoom to use GenericQueue 2021-07-29 14:51:16 -06:00
Neil Dorin
0cd3c1bdc5 fix(ZoomRoom): #767 #768 Adds Output2 on ZoomRoom and updates to UI for VTC
Updates EssentialsVideoCodecUiDriver and codec classes to better deal with dynamic use of IHasCallHistory and
2021-07-29 13:01:02 -06:00
49 changed files with 4248 additions and 2346 deletions

View File

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

View File

@@ -8,12 +8,9 @@ on:
- bugfix/*
- release/*
- development
pull_request:
branches:
- development
env:
# solution path doesn't need slashes unless there it is multiple folders deep
# solution path doesn't need slashes unless it is multiple folders deep
# solution name does not include extension. .sln is assumed
SOLUTION_PATH: PepperDashEssentials
SOLUTION_FILE: PepperDashEssentials

View File

@@ -524,13 +524,22 @@ namespace PepperDash.Essentials
}
private static void CreateMobileControlBridge(IEssentialsRoom room)
private static void CreateMobileControlBridge(object room)
{
var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return;
mobileControl.CreateMobileControlRoomBridge(room, mobileControl);
var mobileControl3 = mobileControl as IMobileControl3;
if (mobileControl3 != null)
{
mobileControl3.CreateMobileControlRoomBridge(room as IEssentialsRoom, mobileControl);
}
else
{
mobileControl.CreateMobileControlRoomBridge(room as EssentialsRoomBase, mobileControl);
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control Bridge Added...");
}

View File

@@ -207,7 +207,7 @@ namespace PepperDash.Essentials
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls;
Initialize();
InitializeRoom();
}
catch (Exception e)
{
@@ -215,7 +215,7 @@ namespace PepperDash.Essentials
}
}
void Initialize()
void InitializeRoom()
{
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;

View File

@@ -156,7 +156,7 @@ namespace PepperDash.Essentials
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IRoutingSinkWithSwitching;
Initialize();
InitializeRoom();
}
catch (Exception e)
{
@@ -164,7 +164,7 @@ namespace PepperDash.Essentials
}
}
void Initialize()
void InitializeRoom()
{
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;

View File

@@ -226,7 +226,7 @@ namespace PepperDash.Essentials
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls;
Initialize();
InitializeRoom();
}
catch (Exception e)
{
@@ -234,7 +234,7 @@ namespace PepperDash.Essentials
}
}
void Initialize()
void InitializeRoom()
{
try
{
@@ -454,7 +454,8 @@ namespace PepperDash.Essentials
else
{
Debug.Console(1, this, "sourceListKey present but not yet implemented");
throw new NotImplementedException();
RunRouteAction(routeKey, new Action(() => { }));
}
}
@@ -471,7 +472,11 @@ namespace PepperDash.Essentials
RunRouteAction(routeKey, successCallback);
}
else
throw new NotImplementedException();
{
Debug.Console(1, this, "sourceListKey present but not yet implemented");
RunRouteAction(routeKey, successCallback);
}
}
/// <summary>

View File

@@ -17,7 +17,7 @@ using PepperDash.Core;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IHasDefaultDisplay
{
bool ExcludeFromGlobalFunctions { get; }
@@ -31,7 +31,7 @@ namespace PepperDash.Essentials
}
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange,
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback
IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay
{
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
@@ -39,10 +39,6 @@ namespace PepperDash.Essentials
IHasScheduleAwareness ScheduleSource { get; }
BoolFeedback InCallFeedback { get; }
BoolFeedback PrivacyModeIsOnFeedback { get; }
string DefaultCodecRouteString { get; }
}
}

View File

@@ -49,6 +49,16 @@ namespace PepperDash.Essentials
/// 1006
/// </summary>
public const uint CallEndAllConfirmVisible = 1006;
/// <summary>
/// 1007
/// </summary>
public const uint MeetingPasswordVisible = 1007;
/// <summary>
/// 1008
/// </summary>
public const uint MeetingLeavePress = 1008;
@@ -103,7 +113,7 @@ namespace PepperDash.Essentials
/// <summary>
/// 1202
/// </summary>
public const uint VCStagingInactivePopoverVisible = 1202;
public const uint VCStagingInactivePopoverWithRecentsVisible = 1202;
/// <summary>
///
/// </summary>
@@ -121,6 +131,11 @@ namespace PepperDash.Essentials
/// </summary>
public const uint VCRecentsVisible = 1206;
/// <summary>
/// 1202
/// </summary>
public const uint VCStagingInactivePopoverWithoutRecentsVisible = 1207;
/// <summary>
/// 1208
/// </summary>
@@ -148,6 +163,11 @@ namespace PepperDash.Essentials
public const uint VCFavoriteVisibleStart = 1221;
// RANGE IN USE
public const uint VCFavoriteVisibleEnd = 1225;
/// <summary>
/// 1230
/// </summary>
public const uint VCStagingMeetNowPress = 1230;
/// <summary>
/// 1231
/// </summary>
@@ -243,6 +263,10 @@ namespace PepperDash.Essentials
/// </summary>
public const uint VCCameraSelectBarWithoutModeVisible = 1261;
/// <summary>
/// 1262
/// </summary>
public const uint VCCameraAutoModeIsOnFb = 1262;
/// <summary>
/// 1271
@@ -744,9 +768,9 @@ namespace PepperDash.Essentials
/// </summary>
public const uint SourceBackgroundOverlayClosePress = 15044;
/// <summary>
/// 15045 - Visibility for the bar containing call navigation button list
/// 15045
/// </summary>
public const uint CallStagingBarVisible = 15045;
public const uint ZoomRoomContentSharingVisible = 15045;
/// <summary>
/// 15046
/// </summary>
@@ -835,6 +859,11 @@ namespace PepperDash.Essentials
/// 15067
/// </summary>
public const uint NotificationRibbonVisible = 15067;
/// <summary>
/// 15068
/// </summary>
public const uint HeaderMeetingInfoVisible = 15068;
/// <summary>
/// 15083 - Press for Call help desk on AC/VC
/// </summary>
@@ -939,5 +968,24 @@ namespace PepperDash.Essentials
/// 15214
/// </summary>
public const uint PinDialogDot4 = 15214;
// Password Prompt Dialog **************************
/// <summary>
/// 15301
/// </summary>
public const uint PasswordPromptDialogVisible = 15301;
/// <summary>
/// 15302
/// </summary>
public const uint PasswordPromptTextPress = 15302;
/// <summary>
/// 15306
/// </summary>
public const uint PasswordPromptCancelPress = 15306;
/// <summary>
/// 15307
/// </summary>
public const uint PasswordPromptErrorVisible = 15307;
}
}

View File

@@ -27,6 +27,33 @@ namespace PepperDash.Essentials
/// 1004
/// </summary>
public const uint CallSharedSourceNameText = 1004;
/// <summary>
/// 1005
/// </summary>
public const uint MeetingIdText = 1005;
/// <summary>
/// 1006
/// </summary>
public const uint MeetingHostText = 1006;
/// <summary>
/// 1007
/// </summary>
public const uint MeetingPasswordText = 1007;
/// <summary>
/// 1008
/// </summary>
public const uint MeetingLeaveText = 1008;
/// <summary>
/// 1009
/// </summary>
public const uint MeetingNameText = 1009;
///<summary>
/// 1240 - Used to determine text for meeting start button
///</summary>
public const uint MeetingStartButtonText = 1240;
/// <summary>
@@ -118,6 +145,14 @@ namespace PepperDash.Essentials
//----- through 3120
/// <summary>
/// 3201
/// </summary>
public const uint PasswordPromptMessageText = 3201;
/// <summary>
/// 3202
/// </summary>
public const uint PasswordPromptPasswordText = 3202;
/// <summary>
/// 3812

View File

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

View File

@@ -12,6 +12,7 @@ using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
@@ -164,7 +165,7 @@ namespace PepperDash.Essentials
CallCaretVisible = tempJoin + 10;
TriList.SetSigFalseAction(tempJoin, () =>
{
avDriver.ShowActiveCallsList();
avDriver.ShowActiveCallsListOrMeetingInfo();
if(avDriver.CurrentRoom.InCallFeedback.BoolValue)
CaretInterlock.ShowInterlocked(CallCaretVisible);
});
@@ -191,32 +192,56 @@ namespace PepperDash.Essentials
return;
}
var meetingInfoCodec = codec as IHasMeetingInfo;
// 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)
{
HeaderCallButtonIconSig.StringValue = "DND";
//HeaderCallButton.SetIcon(HeaderListButton.OnHook);
}
else if (codec.ActiveCalls.Any(c => c.Type == eCodecCallType.Video))
{
HeaderCallButtonIconSig.StringValue = "Misc-06_Dark";
//HeaderCallButton.SetIcon(HeaderListButton.Camera);
//TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 2);
}
//HeaderCallButton.SetIcon(HeaderListButton.Camera);
//TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 2);
else
{
HeaderCallButtonIconSig.StringValue = "Misc-09_Dark";
}
//HeaderCallButton.SetIcon(HeaderListButton.Phone);
//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>
@@ -256,7 +281,7 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.HeaderCallStatusLabelPress,
() =>
{
avDriver.ShowActiveCallsList();
avDriver.ShowActiveCallsListOrMeetingInfo();
if (avDriver.CurrentRoom.InCallFeedback.BoolValue)
CaretInterlock.ShowInterlocked(CallCaretVisible);
});
@@ -354,6 +379,8 @@ namespace PepperDash.Essentials
headerPopupShown = true;
else if (e.NewJoin == UIBoolJoin.HeaderActiveCallsListVisible)
headerPopupShown = true;
else if (e.NewJoin == UIBoolJoin.HeaderMeetingInfoVisible)
headerPopupShown = true;
else if (e.NewJoin == UIBoolJoin.HelpPageVisible)
headerPopupShown = true;
else if (e.NewJoin == UIBoolJoin.MeetingsOrContacMethodsListVisible)

View File

@@ -918,6 +918,7 @@ namespace PepperDash.Essentials
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = true;
TriList.BooleanInput[UIBoolJoin.VolumeSingleMute1Visible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
}
}

View File

@@ -1,326 +1,326 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
using PepperDash.Essentials.Devices.Displays;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.UIDrivers
{
public class EssentialsHuddleTechPageDriver : PanelDriverBase
{
/// <summary>
///
/// </summary>
SmartObjectDynamicList MenuList;
/// <summary>
///
/// </summary>
SubpageReferenceList StatusList;
/// <summary>
/// The list of display controls
/// </summary>
SubpageReferenceList DisplayList;
/// <summary>
/// References lines in the list against device instances
/// </summary>
Dictionary<ICommunicationMonitor, uint> StatusListDeviceIndexes;
/// <summary>
///
/// </summary>
JoinedSigInterlock PagesInterlock;
/// <summary>
/// 1
/// </summary>
public const uint JoinText = 1;
CTimer PinAuthorizedTimer;
EssentialsRoomTechConfig Config;
StringBuilder PinEntryBuilder = new StringBuilder(4);
bool IsAuthorized;
SmartObjectNumeric PinKeypad;
/// <summary>
///
/// </summary>
/// <param name="trilist"></param>
/// <param name="parent"></param>
public EssentialsHuddleTechPageDriver(BasicTriListWithSmartObject trilist, EssentialsRoomTechConfig config)
: base(trilist)
{
Config = config;
PagesInterlock = new JoinedSigInterlock(trilist);
PagesInterlock.SetButDontShow(UIBoolJoin.TechSystemStatusVisible);
trilist.SetSigFalseAction(UIBoolJoin.TechExitButton, Hide);
MenuList = new SmartObjectDynamicList(trilist.SmartObjects[UISmartObjectJoin.TechMenuList],
true, 3100);
MenuList.SetFeedback(1, true); // initial fb
ushort count = 0;
MenuList.SetItemMainText(1, "System Status");
MenuList.SetItemButtonAction(1, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechSystemStatusVisible);
MenuList.SetFeedback(1, true);
});
MenuList.SetItemMainText(2, "Display Controls");
MenuList.SetItemButtonAction(2, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechDisplayControlsVisible);
MenuList.SetFeedback(2, true);
});
count = 2;
// Don't show panel setup on iPad or xpanel
if (TriList is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button)
{
count++;
MenuList.SetItemMainText(count, "Panel Setup");
MenuList.SetItemButtonAction(count, b =>
{
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechPanelSetupVisible);
MenuList.SetFeedback(count, true);
});
}
MenuList.Count = count;
BuildStatusList();
BuildDisplayList();
SetupPinModal();
}
/// <summary>
///
/// </summary>
public override void Show()
{
// divert to PIN if we need auth
if (IsAuthorized)
{
// Cancel the auth timer so we don't deauth after coming back in
if (PinAuthorizedTimer != null)
PinAuthorizedTimer.Stop();
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, true);
PagesInterlock.Show();
base.Show();
}
else
{
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, true);
}
}
/// <summary>
///
/// </summary>
public override void Hide()
{
// Leave it authorized for 60 seconds.
if (IsAuthorized)
PinAuthorizedTimer = new CTimer(o => {
IsAuthorized = false;
PinAuthorizedTimer = null;
}, 60000);
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, false);
PagesInterlock.Hide();
base.Hide();
}
/// <summary>
/// Wire up the keypad and buttons
/// </summary>
void SetupPinModal()
{
TriList.SetSigFalseAction(UIBoolJoin.PinDialogCancelPress, CancelPinDialog);
PinKeypad = new SmartObjectNumeric(TriList.SmartObjects[UISmartObjectJoin.TechPinDialogKeypad], true);
PinKeypad.Digit0.UserObject = new Action<bool>(b => { if (b)DialPinDigit('0'); });
PinKeypad.Digit1.UserObject = new Action<bool>(b => { if (b)DialPinDigit('1'); });
PinKeypad.Digit2.UserObject = new Action<bool>(b => { if (b)DialPinDigit('2'); });
PinKeypad.Digit3.UserObject = new Action<bool>(b => { if (b)DialPinDigit('3'); });
PinKeypad.Digit4.UserObject = new Action<bool>(b => { if (b)DialPinDigit('4'); });
PinKeypad.Digit5.UserObject = new Action<bool>(b => { if (b)DialPinDigit('5'); });
PinKeypad.Digit6.UserObject = new Action<bool>(b => { if (b)DialPinDigit('6'); });
PinKeypad.Digit7.UserObject = new Action<bool>(b => { if (b)DialPinDigit('7'); });
PinKeypad.Digit8.UserObject = new Action<bool>(b => { if (b)DialPinDigit('8'); });
PinKeypad.Digit9.UserObject = new Action<bool>(b => { if (b)DialPinDigit('9'); });
}
/// <summary>
///
/// </summary>
/// <param name="d"></param>
void DialPinDigit(char d)
{
PinEntryBuilder.Append(d);
var len = PinEntryBuilder.Length;
SetPinDotsFeedback(len);
// check it!
if (len == 4)
{
if (Config.Password == PinEntryBuilder.ToString())
{
IsAuthorized = true;
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
Show();
}
else
{
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, true);
new CTimer(o =>
{
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, false);
}, 1500);
}
PinEntryBuilder.Remove(0, len); // clear it either way
}
}
/// <summary>
/// Draws the dots as pin is entered
/// </summary>
/// <param name="len"></param>
void SetPinDotsFeedback(int len)
{
TriList.SetBool(UIBoolJoin.PinDialogDot1, len >= 1);
TriList.SetBool(UIBoolJoin.PinDialogDot2, len >= 2);
TriList.SetBool(UIBoolJoin.PinDialogDot3, len >= 3);
TriList.SetBool(UIBoolJoin.PinDialogDot4, len == 4);
}
/// <summary>
/// Does what it says
/// </summary>
void CancelPinDialog()
{
PinEntryBuilder.Remove(0, PinEntryBuilder.Length);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
}
/// <summary>
///
/// </summary>
void BuildStatusList()
{
StatusList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechStatusList, 3, 3, 3);
StatusListDeviceIndexes = new Dictionary<ICommunicationMonitor, uint>();
uint i = 0;
foreach (var d in DeviceManager.AllDevices)
{
// make sure it is both ICommunicationMonitor and a Device
var sd = d as ICommunicationMonitor;
if (sd == null)
continue;
var dd = sd as Device;
if(dd == null)
continue;
i++;
StatusList.StringInputSig(i, 1).StringValue = dd.Name;
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)sd.CommunicationMonitor.Status;
StatusListDeviceIndexes.Add(sd, i);
sd.CommunicationMonitor.StatusChange += CommunicationMonitor_StatusChange ;
}
StatusList.Count = (ushort)i;
}
/// <summary>
/// Builds the list of display controls
/// </summary>
void BuildDisplayList()
{
DisplayList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechDisplayControlsList, 10, 3, 3);
var devKeys = ConfigReader.ConfigObject.Devices.Where(d =>
d.Group.Equals("display", StringComparison.OrdinalIgnoreCase)
|| d.Group.Equals("projector", StringComparison.OrdinalIgnoreCase))
.Select(dd => dd.Key);
var disps = DeviceManager.AllDevices.Where(d =>
devKeys.Contains(d.Key));
ushort i = 0;
foreach (var disp in disps)
{
var display = disp as DisplayBase;
if (display != null)
{
i++;
DisplayList.StringInputSig(i, 1).StringValue = display.Name;
DisplayList.GetBoolFeedbackSig(i, 1).SetSigFalseAction(display.PowerOn);
DisplayList.GetBoolFeedbackSig(i, 2).SetSigFalseAction(display.PowerOff);
if (display is TwoWayDisplayBase)
{
var powerOnSig = DisplayList.BoolInputSig(i, 1);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkInputSig(powerOnSig);
var powerOffSig = DisplayList.BoolInputSig(1, 2);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkComplementInputSig(powerOffSig);
}
DisplayList.GetBoolFeedbackSig(i, 3).SetSigFalseAction(() =>
{ if (display is IInputHdmi1) (display as IInputHdmi1).InputHdmi1(); });
DisplayList.GetBoolFeedbackSig(i, 4).SetSigFalseAction(() =>
{ if (display is IInputHdmi2) (display as IInputHdmi2).InputHdmi2(); });
DisplayList.GetBoolFeedbackSig(i, 5).SetSigFalseAction(() =>
{ if (display is IInputHdmi3) (display as IInputHdmi3).InputHdmi3(); });
//DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
//{ if (display is IInputHdmi4) (display as IInputHdmi4).InputHdmi4(); });
DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
{ if (display is IInputDisplayPort1) (display as IInputDisplayPort1).InputDisplayPort1(); });
// Figure out some way to provide current input feedback
if (display is TwoWayDisplayBase)
{
(display as TwoWayDisplayBase).CurrentInputFeedback.OutputChange += CurrentInputFeedback_OutputChange;
}
}
}
DisplayList.Count = i;
}
void CurrentInputFeedback_OutputChange(object sender, EventArgs e)
{
}
/// <summary>
///
/// </summary>
void CommunicationMonitor_StatusChange(object sender, MonitorStatusChangeEventArgs e)
{
var c = sender as ICommunicationMonitor;
if (StatusListDeviceIndexes.ContainsKey(c))
{
var i = StatusListDeviceIndexes[c];
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)e.Status;
}
}
}
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
using PepperDash.Essentials.Devices.Displays;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.UIDrivers
{
public class EssentialsHuddleTechPageDriver : PanelDriverBase
{
/// <summary>
///
/// </summary>
SmartObjectDynamicList MenuList;
/// <summary>
///
/// </summary>
SubpageReferenceList StatusList;
/// <summary>
/// The list of display controls
/// </summary>
SubpageReferenceList DisplayList;
/// <summary>
/// References lines in the list against device instances
/// </summary>
Dictionary<ICommunicationMonitor, uint> StatusListDeviceIndexes;
/// <summary>
///
/// </summary>
JoinedSigInterlock PagesInterlock;
/// <summary>
/// 1
/// </summary>
public const uint JoinText = 1;
CTimer PinAuthorizedTimer;
EssentialsRoomTechConfig Config;
StringBuilder PinEntryBuilder = new StringBuilder(4);
bool IsAuthorized;
SmartObjectNumeric PinKeypad;
/// <summary>
///
/// </summary>
/// <param name="trilist"></param>
/// <param name="parent"></param>
public EssentialsHuddleTechPageDriver(BasicTriListWithSmartObject trilist, EssentialsRoomTechConfig config)
: base(trilist)
{
Config = config;
PagesInterlock = new JoinedSigInterlock(trilist);
PagesInterlock.SetButDontShow(UIBoolJoin.TechSystemStatusVisible);
trilist.SetSigFalseAction(UIBoolJoin.TechExitButton, Hide);
MenuList = new SmartObjectDynamicList(trilist.SmartObjects[UISmartObjectJoin.TechMenuList],
true, 3100);
MenuList.SetFeedback(1, true); // initial fb
ushort count = 0;
MenuList.SetItemMainText(1, "System Status");
MenuList.SetItemButtonAction(1, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechSystemStatusVisible);
MenuList.SetFeedback(1, true);
});
MenuList.SetItemMainText(2, "Display Controls");
MenuList.SetItemButtonAction(2, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechDisplayControlsVisible);
MenuList.SetFeedback(2, true);
});
count = 2;
// Don't show panel setup on iPad or xpanel
if (TriList is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button)
{
count++;
MenuList.SetItemMainText(count, "Panel Setup");
MenuList.SetItemButtonAction(count, b =>
{
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechPanelSetupVisible);
MenuList.SetFeedback(count, true);
});
}
MenuList.Count = count;
BuildStatusList();
BuildDisplayList();
SetupPinModal();
}
/// <summary>
///
/// </summary>
public override void Show()
{
// divert to PIN if we need auth
if (IsAuthorized)
{
// Cancel the auth timer so we don't deauth after coming back in
if (PinAuthorizedTimer != null)
PinAuthorizedTimer.Stop();
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, true);
PagesInterlock.Show();
base.Show();
}
else
{
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, true);
}
}
/// <summary>
///
/// </summary>
public override void Hide()
{
// Leave it authorized for 60 seconds.
if (IsAuthorized)
PinAuthorizedTimer = new CTimer(o => {
IsAuthorized = false;
PinAuthorizedTimer = null;
}, 60000);
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, false);
PagesInterlock.Hide();
base.Hide();
}
/// <summary>
/// Wire up the keypad and buttons
/// </summary>
void SetupPinModal()
{
TriList.SetSigFalseAction(UIBoolJoin.PinDialogCancelPress, CancelPinDialog);
PinKeypad = new SmartObjectNumeric(TriList.SmartObjects[UISmartObjectJoin.TechPinDialogKeypad], true);
PinKeypad.Digit0.UserObject = new Action<bool>(b => { if (b)DialPinDigit('0'); });
PinKeypad.Digit1.UserObject = new Action<bool>(b => { if (b)DialPinDigit('1'); });
PinKeypad.Digit2.UserObject = new Action<bool>(b => { if (b)DialPinDigit('2'); });
PinKeypad.Digit3.UserObject = new Action<bool>(b => { if (b)DialPinDigit('3'); });
PinKeypad.Digit4.UserObject = new Action<bool>(b => { if (b)DialPinDigit('4'); });
PinKeypad.Digit5.UserObject = new Action<bool>(b => { if (b)DialPinDigit('5'); });
PinKeypad.Digit6.UserObject = new Action<bool>(b => { if (b)DialPinDigit('6'); });
PinKeypad.Digit7.UserObject = new Action<bool>(b => { if (b)DialPinDigit('7'); });
PinKeypad.Digit8.UserObject = new Action<bool>(b => { if (b)DialPinDigit('8'); });
PinKeypad.Digit9.UserObject = new Action<bool>(b => { if (b)DialPinDigit('9'); });
}
/// <summary>
///
/// </summary>
/// <param name="d"></param>
void DialPinDigit(char d)
{
PinEntryBuilder.Append(d);
var len = PinEntryBuilder.Length;
SetPinDotsFeedback(len);
// check it!
if (len == 4)
{
if (Config.Password == PinEntryBuilder.ToString())
{
IsAuthorized = true;
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
Show();
}
else
{
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, true);
new CTimer(o =>
{
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, false);
}, 1500);
}
PinEntryBuilder.Remove(0, len); // clear it either way
}
}
/// <summary>
/// Draws the dots as pin is entered
/// </summary>
/// <param name="len"></param>
void SetPinDotsFeedback(int len)
{
TriList.SetBool(UIBoolJoin.PinDialogDot1, len >= 1);
TriList.SetBool(UIBoolJoin.PinDialogDot2, len >= 2);
TriList.SetBool(UIBoolJoin.PinDialogDot3, len >= 3);
TriList.SetBool(UIBoolJoin.PinDialogDot4, len == 4);
}
/// <summary>
/// Does what it says
/// </summary>
void CancelPinDialog()
{
PinEntryBuilder.Remove(0, PinEntryBuilder.Length);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
}
/// <summary>
///
/// </summary>
void BuildStatusList()
{
StatusList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechStatusList, 3, 3, 3);
StatusListDeviceIndexes = new Dictionary<ICommunicationMonitor, uint>();
uint i = 0;
foreach (var d in DeviceManager.AllDevices)
{
// make sure it is both ICommunicationMonitor and a Device
var sd = d as ICommunicationMonitor;
if (sd == null)
continue;
var dd = sd as Device;
if(dd == null)
continue;
i++;
StatusList.StringInputSig(i, 1).StringValue = dd.Name;
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)sd.CommunicationMonitor.Status;
StatusListDeviceIndexes.Add(sd, i);
sd.CommunicationMonitor.StatusChange += CommunicationMonitor_StatusChange ;
}
StatusList.Count = (ushort)i;
}
/// <summary>
/// Builds the list of display controls
/// </summary>
void BuildDisplayList()
{
DisplayList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechDisplayControlsList, 10, 3, 3);
var devKeys = ConfigReader.ConfigObject.Devices.Where(d =>
d.Group.Equals("display", StringComparison.OrdinalIgnoreCase)
|| d.Group.Equals("projector", StringComparison.OrdinalIgnoreCase))
.Select(dd => dd.Key);
var disps = DeviceManager.AllDevices.Where(d =>
devKeys.Contains(d.Key));
ushort i = 0;
foreach (var disp in disps)
{
var display = disp as DisplayBase;
if (display != null)
{
i++;
DisplayList.StringInputSig(i, 1).StringValue = display.Name;
DisplayList.GetBoolFeedbackSig(i, 1).SetSigFalseAction(display.PowerOn);
DisplayList.GetBoolFeedbackSig(i, 2).SetSigFalseAction(display.PowerOff);
if (display is TwoWayDisplayBase)
{
var powerOnSig = DisplayList.BoolInputSig(i, 1);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkInputSig(powerOnSig);
var powerOffSig = DisplayList.BoolInputSig(1, 2);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkComplementInputSig(powerOffSig);
}
DisplayList.GetBoolFeedbackSig(i, 3).SetSigFalseAction(() =>
{ if (display is IInputHdmi1) (display as IInputHdmi1).InputHdmi1(); });
DisplayList.GetBoolFeedbackSig(i, 4).SetSigFalseAction(() =>
{ if (display is IInputHdmi2) (display as IInputHdmi2).InputHdmi2(); });
DisplayList.GetBoolFeedbackSig(i, 5).SetSigFalseAction(() =>
{ if (display is IInputHdmi3) (display as IInputHdmi3).InputHdmi3(); });
//DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
//{ if (display is IInputHdmi4) (display as IInputHdmi4).InputHdmi4(); });
DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
{ if (display is IInputDisplayPort1) (display as IInputDisplayPort1).InputDisplayPort1(); });
// Figure out some way to provide current input feedback
if (display is TwoWayDisplayBase)
{
(display as TwoWayDisplayBase).CurrentInputFeedback.OutputChange += CurrentInputFeedback_OutputChange;
}
}
}
DisplayList.Count = i;
}
void CurrentInputFeedback_OutputChange(object sender, EventArgs e)
{
}
/// <summary>
///
/// </summary>
void CommunicationMonitor_StatusChange(object sender, MonitorStatusChangeEventArgs e)
{
var c = sender as ICommunicationMonitor;
if (c != null && StatusListDeviceIndexes.ContainsKey(c))
{
var i = StatusListDeviceIndexes[c];
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)e.Status;
}
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.UI;
@@ -8,11 +9,13 @@ using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.PageManagers;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
namespace PepperDash.Essentials
{
@@ -98,6 +101,9 @@ namespace PepperDash.Essentials
/// </summary>
public SubpageReferenceList MeetingOrContactMethodModalSrl { get; set; }
public uint CallListOrMeetingInfoPopoverVisibilityJoin { get; private set; }
/// <summary>
/// The list of buttons on the header. Managed with visibility only
/// </summary>
@@ -173,10 +179,38 @@ namespace PepperDash.Essentials
/// </summary>
public PepperDash.Essentials.Core.Touchpanels.Keyboards.HabaneroKeyboardController Keyboard { get; private set; }
private UiDisplayMode _currentMode;
private bool _isZoomRoomWithNoExternalSources
{
get
{
return CurrentRoom.VideoCodec is Essentials.Devices.Common.VideoCodec.ZoomRoom.ZoomRoom && _sourceListCount <= 1;
}
}
private uint _sourceListCount;
/// <summary>
/// The mode showing. Presentation or call.
/// </summary>
UiDisplayMode CurrentMode = UiDisplayMode.Start;
UiDisplayMode CurrentMode
{
get
{
return _currentMode;
}
set
{
if (value != _currentMode)
{
_currentMode = value;
SetActivityFooterFeedbacks();
}
}
}
CTimer NextMeetingTimer;
@@ -207,6 +241,7 @@ namespace PepperDash.Essentials
MeetingOrContactMethodModalSrl = new SubpageReferenceList(TriList, UISmartObjectJoin.MeetingListSRL, 3, 3, 5);
CurrentMode = UiDisplayMode.Start;
// buttons are added in SetCurrentRoom
//HeaderButtonsList = new SmartObjectHeaderButtonList(TriList.SmartObjects[UISmartObjectJoin.HeaderButtonList]);
@@ -331,15 +366,17 @@ namespace PepperDash.Essentials
/// <summary>
/// Allows PopupInterlock to be toggled if the calls list is already visible, or if the codec is in a call
/// </summary>
public void ShowActiveCallsList()
public void ShowActiveCallsListOrMeetingInfo()
{
TriList.SetBool(UIBoolJoin.CallEndAllConfirmVisible, true);
if(PopupInterlock.CurrentJoin == UIBoolJoin.HeaderActiveCallsListVisible)
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HeaderActiveCallsListVisible);
if(PopupInterlock.CurrentJoin == CallListOrMeetingInfoPopoverVisibilityJoin)
PopupInterlock.ShowInterlockedWithToggle(CallListOrMeetingInfoPopoverVisibilityJoin);
else
{
if((CurrentRoom.ScheduleSource as VideoCodecBase).IsInCall)
PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HeaderActiveCallsListVisible);
if(CurrentRoom.VideoCodec.IsInCall)
PopupInterlock.ShowInterlockedWithToggle(CallListOrMeetingInfoPopoverVisibilityJoin);
}
}
@@ -435,79 +472,92 @@ namespace PepperDash.Essentials
/// </summary>
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
RefreshMeetingsList();
// check meetings list for the closest, joinable meeting
var ss = CurrentRoom.ScheduleSource;
var meetings = ss.CodecSchedule.Meetings;
if (meetings.Count > 0)
{
// If the room is off pester the user
// If the room is on, and the meeting is joinable
// and the LastMeetingDismissed != this meeting
if (meetings.Count <= 0)
{
return;
}
// 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);
Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
CurrentRoom.OnFeedback.BoolValue,
LastMeetingDismissedId,
lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToShortTimeString() : "");
var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId);
Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
CurrentRoom.OnFeedback.BoolValue,
LastMeetingDismissedId,
lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : "");
var meeting = meetings.LastOrDefault(m => m.Joinable);
if (CurrentRoom.OnFeedback.BoolValue
&& lastMeetingDismissed == meeting)
{
return;
}
var meeting = meetings.LastOrDefault(m => m.Joinable);
if (CurrentRoom.OnFeedback.BoolValue
&& lastMeetingDismissed == meeting)
{
// meeting no longer joinable, hide popup
if(meeting == null)
HideNextMeetingPopup();
LastMeetingDismissedId = null;
// Clear the popup when we run out of meetings
if (meeting == null)
{
HideNextMeetingPopup();
}
else
{
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Upcoming meeting");
TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToShortTimeString());
TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToShortTimeString());
TriList.SetString(UIStringJoin.NextMeetingTitleText, meeting.Title);
TriList.SetString(UIStringJoin.NextMeetingNameText, meeting.Organizer);
TriList.SetString(UIStringJoin.NextMeetingButtonLabel, "Join");
TriList.SetSigFalseAction(UIBoolJoin.NextMeetingJoinPress, () =>
{
HideNextMeetingPopup();
PopupInterlock.Hide();
RoomOnAndDialMeeting(meeting);
});
TriList.SetString(UIStringJoin.NextMeetingSecondaryButtonLabel, "Show Schedule");
TriList.SetSigFalseAction(UIBoolJoin.CalendarHeaderButtonPress, () =>
{
HideNextMeetingPopup();
//CalendarPress();
RefreshMeetingsList();
PopupInterlock.ShowInterlocked(UIBoolJoin.MeetingsOrContacMethodsListVisible);
});
var indexOfNext = meetings.IndexOf(meeting) + 1;
return;
}
// indexOf = 3, 4 meetings :
if (indexOfNext < meetings.Count)
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText,
meetings[indexOfNext].StartTime.ToShortTimeString());
else
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, "No more meetings today");
LastMeetingDismissedId = null;
// Clear the popup when we run out of meetings
if (meeting == null)
{
HideNextMeetingPopup();
}
else
{
TriList.SetSigFalseAction(UIBoolJoin.NextMeetingModalClosePress, () =>
{
// Mark the meeting to not re-harass the user
if(CurrentRoom.OnFeedback.BoolValue)
LastMeetingDismissedId = meeting.Id;
HideNextMeetingPopup();
});
TriList.SetBool(UIBoolJoin.NextMeetingModalVisible, true);
}
}
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Upcoming meeting");
TriList.SetString(UIStringJoin.NextMeetingStartTimeText, meeting.StartTime.ToString("t", Global.Culture));
TriList.SetString(UIStringJoin.NextMeetingEndTimeText, meeting.EndTime.ToString("t", Global.Culture));
TriList.SetString(UIStringJoin.NextMeetingTitleText, meeting.Title);
TriList.SetString(UIStringJoin.NextMeetingNameText, meeting.Organizer);
TriList.SetString(UIStringJoin.NextMeetingButtonLabel, "Join");
TriList.SetSigFalseAction(UIBoolJoin.NextMeetingJoinPress, () =>
{
HideNextMeetingPopup();
PopupInterlock.Hide();
RoomOnAndDialMeeting(meeting);
});
TriList.SetString(UIStringJoin.NextMeetingSecondaryButtonLabel, "Show Schedule");
TriList.SetSigFalseAction(UIBoolJoin.CalendarHeaderButtonPress, () =>
{
HideNextMeetingPopup();
//CalendarPress();
RefreshMeetingsList();
PopupInterlock.ShowInterlocked(UIBoolJoin.MeetingsOrContacMethodsListVisible);
});
var indexOfNext = meetings.IndexOf(meeting) + 1;
// indexOf = 3, 4 meetings :
if (indexOfNext < meetings.Count)
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText,
meetings[indexOfNext].StartTime.ToString("t", Global.Culture));
else
TriList.SetString(UIStringJoin.NextMeetingFollowingMeetingText, "No more meetings today");
TriList.SetSigFalseAction(UIBoolJoin.NextMeetingModalClosePress, () =>
{
// Mark the meeting to not re-harass the user
if(CurrentRoom.OnFeedback.BoolValue)
LastMeetingDismissedId = meeting.Id;
HideNextMeetingPopup();
});
TriList.SetBool(UIBoolJoin.NextMeetingModalVisible, true);
}
}
/// <summary>
@@ -533,19 +583,26 @@ namespace PepperDash.Essentials
/// </summary>
void RoomOnAndDialMeeting(Meeting meeting)
{
Debug.Console(1, "[RoomOnAndDialMeeting] Joining meeting [{0}]", meeting);
Action dialAction = () =>
{
var d = CurrentRoom.ScheduleSource as VideoCodecBase;
if (d != null)
{
Debug.Console(1,
"[RoomOnAndDialMeeting] [dialAction] Sending command to codec to join meeting {0}", meeting);
d.Dial(meeting);
LastMeetingDismissedId = meeting.Id; // To prevent prompts for already-joined call
}
};
if (CurrentRoom.OnFeedback.BoolValue)
dialAction();
if (CurrentRoom.OnFeedback.BoolValue)
{
Debug.Console(1, "[RoomOnAndDialMeeting] Room is on.");
dialAction();
}
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
EventHandler<FeedbackEventArgs> oneTimeHandler = null;
oneTimeHandler = (o, a) =>
@@ -607,11 +664,39 @@ namespace PepperDash.Essentials
/// </summary>
void SetActivityFooterFeedbacks()
{
CallButtonSig.BoolValue = CurrentMode == UiDisplayMode.Call
&& CurrentRoom.ShutdownType == eShutdownType.None;
ShareButtonSig.BoolValue = CurrentMode == UiDisplayMode.Presentation
&& CurrentRoom.ShutdownType == eShutdownType.None;
EndMeetingButtonSig.BoolValue = CurrentRoom.ShutdownType != eShutdownType.None;
if (CurrentRoom != null)
{
var startMode = CurrentMode == UiDisplayMode.Start;
var presentationMode = CurrentMode == UiDisplayMode.Presentation;
var callMode = CurrentMode == UiDisplayMode.Call;
TriList.SetBool(StartPageVisibleJoin, startMode ? true : false);
if (presentationMode &&_isZoomRoomWithNoExternalSources)
{
// For now, if this is a Zoom Room and there are no shareable sources just display the informational subpage
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false);
TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, true);
}
else
{
// Otherwise, show the staging bar
TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, false);
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, presentationMode ? true : false);
}
if (!presentationMode)
{
TriList.SetBool(UIBoolJoin.ZoomRoomContentSharingVisible, false);
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
}
CallButtonSig.BoolValue = callMode
&& CurrentRoom.ShutdownType == eShutdownType.None;
ShareButtonSig.BoolValue = presentationMode
&& CurrentRoom.ShutdownType == eShutdownType.None;
EndMeetingButtonSig.BoolValue = CurrentRoom.ShutdownType != eShutdownType.None;
}
}
/// <summary>
@@ -623,14 +708,13 @@ namespace PepperDash.Essentials
return;
HideLogo();
HideNextMeetingPopup();
TriList.SetBool(StartPageVisibleJoin, false);
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false);
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
//TriList.SetBool(StartPageVisibleJoin, false);
//TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false);
//TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
if (CurrentSourcePageManager != null)
CurrentSourcePageManager.Hide();
PowerOnFromCall();
CurrentMode = UiDisplayMode.Call;
SetActivityFooterFeedbacks();
VCDriver.Show();
}
@@ -643,29 +727,63 @@ namespace PepperDash.Essentials
if (VCDriver.IsVisible)
VCDriver.Hide();
HideNextMeetingPopup();
TriList.SetBool(StartPageVisibleJoin, false);
TriList.SetBool(UIBoolJoin.CallStagingBarVisible, false);
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, true);
// Run default source when room is off and share is pressed
if (!CurrentRoom.OnFeedback.BoolValue)
{
if (!CurrentRoom.OnFeedback.BoolValue)
{
// If there's no default, show UI elements
if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute())
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
}
}
else // room is on show what's active or select a source if nothing is yet active
if (_isZoomRoomWithNoExternalSources)
{
if(CurrentRoom.CurrentSourceInfo == null || CurrentRoom.CurrentSourceInfoKey == CurrentRoom.DefaultCodecRouteString)
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
else if (CurrentSourcePageManager != null)
CurrentSourcePageManager.Show();
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
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)
CurrentSourcePageManager.Hide();
}
else
{
// Run default source when room is off and share is pressed
if (!CurrentRoom.OnFeedback.BoolValue)
{
// If there's no default, show UI elements
if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute())
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
}
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))
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
else if (CurrentSourcePageManager != null)
{
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
CurrentSourcePageManager.Show();
}
}
SetupSourceList();
}
CurrentMode = UiDisplayMode.Presentation;
SetupSourceList();
SetActivityFooterFeedbacks();
}
/// <summary>
@@ -704,9 +822,11 @@ namespace PepperDash.Essentials
/// </summary>
void ShowCurrentSource()
{
if (CurrentRoom.CurrentSourceInfo == null)
if (CurrentRoom.CurrentSourceInfo == null || _isZoomRoomWithNoExternalSources)
return;
CurrentMode = UiDisplayMode.Presentation;
if (CurrentRoom.CurrentSourceInfo.SourceDevice == null)
{
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
@@ -912,6 +1032,18 @@ namespace PepperDash.Essentials
_CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange;
_CurrentRoom.IsCoolingDownFeedback.OutputChange -= CurrentRoom_IsCoolingDownFeedback_OutputChange;
_CurrentRoom.InCallFeedback.OutputChange -= CurrentRoom_InCallFeedback_OutputChange;
var scheduleAwareCodec = _CurrentRoom.VideoCodec as IHasScheduleAwareness;
if (scheduleAwareCodec != null)
{
scheduleAwareCodec.CodecSchedule.MeetingsListHasChanged -= CodecSchedule_MeetingsListHasChanged;
}
var meetingInfoCodec = _CurrentRoom.VideoCodec as IHasMeetingInfo;
if (meetingInfoCodec != null)
{
meetingInfoCodec.MeetingInfoChanged -= meetingInfoCodec_MeetingInfoChanged;
}
}
_CurrentRoom = room;
@@ -944,9 +1076,23 @@ namespace PepperDash.Essentials
_CurrentRoom.CurrentSourceChange += CurrentRoom_SourceInfoChange;
RefreshSourceInfo();
if (_CurrentRoom.VideoCodec is IHasScheduleAwareness)
var scheduleAwareCodec = _CurrentRoom.VideoCodec as IHasScheduleAwareness;
if (scheduleAwareCodec != null)
{
(_CurrentRoom.VideoCodec as IHasScheduleAwareness).CodecSchedule.MeetingsListHasChanged += CodecSchedule_MeetingsListHasChanged;
scheduleAwareCodec.CodecSchedule.MeetingsListHasChanged += CodecSchedule_MeetingsListHasChanged;
}
var meetingInfoCodec = _CurrentRoom.VideoCodec as IHasMeetingInfo;
if (meetingInfoCodec != null)
{
meetingInfoCodec.MeetingInfoChanged += new EventHandler<MeetingInfoEventArgs>(meetingInfoCodec_MeetingInfoChanged);
CallListOrMeetingInfoPopoverVisibilityJoin = UIBoolJoin.HeaderMeetingInfoVisible;
}
else
{
CallListOrMeetingInfoPopoverVisibilityJoin = UIBoolJoin.HeaderActiveCallsListVisible;
}
CallSharingInfoVisibleFeedback = new BoolFeedback(() => _CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue);
@@ -958,7 +1104,8 @@ namespace PepperDash.Essentials
if (_CurrentRoom != null)
_CurrentRoom.CurrentSourceChange += new SourceInfoChangeHandler(CurrentRoom_CurrentSingleSourceChange);
TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, () => _CurrentRoom.RunRouteAction("codecOsd", _CurrentRoom.SourceListKey));
// Moved to EssentialsVideoCodecUiDriver
//TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, () => _CurrentRoom.RunRouteAction("codecOsd", _CurrentRoom.SourceListKey));
(Parent as EssentialsPanelMainInterfaceDriver).HeaderDriver.SetupHeaderButtons(this, CurrentRoom);
}
@@ -969,6 +1116,26 @@ namespace PepperDash.Essentials
}
}
void meetingInfoCodec_MeetingInfoChanged(object sender, MeetingInfoEventArgs e)
{
if (e.Info == null)
{
return;
}
TriList.SetString(UIStringJoin.MeetingIdText, e.Info.Id);
TriList.SetString(UIStringJoin.MeetingHostText, e.Info.Host);
TriList.SetString(UIStringJoin.MeetingNameText, e.Info.Name);
TriList.SetString(UIStringJoin.MeetingPasswordText, e.Info.Password);
// Show the password fields if one is present
TriList.SetBool(UIBoolJoin.MeetingPasswordVisible, !string.IsNullOrEmpty(e.Info.Password));
TriList.SetString(UIStringJoin.CallSharedSourceNameText, e.Info.ShareStatus);
TriList.SetString(UIStringJoin.MeetingLeaveText, e.Info.IsHost ? "End Meeting" : "Leave Meeting");
}
void SetCurrentRoom(IEssentialsHuddleVtc1Room room)
{
if (_CurrentRoom == room) return;
@@ -1082,7 +1249,8 @@ namespace PepperDash.Essentials
Debug.Console(1, "**** KEY {0}", kvp.Key);
}
SourceStagingSrl.Count = (ushort)(i - 1);
_sourceListCount = (i - 1);
SourceStagingSrl.Count = (ushort)_sourceListCount;
}
}
@@ -1105,6 +1273,30 @@ namespace PepperDash.Essentials
/// <param name="type"></param>
void CurrentRoom_CurrentSingleSourceChange(SourceListItem info, ChangeType type)
{
Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange");
// Show the Select a source subpage
if (TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue)
{
Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange SourceStagingBarVisisble: true");
if (_CurrentRoom.CurrentSourceInfo == null || (_CurrentRoom.VideoCodec != null && _CurrentRoom.CurrentSourceInfo.SourceDevice.Key == _CurrentRoom.VideoCodec.OsdSource.Key))
{
Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange Showing SelectASourceVisible");
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
}
else
{
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange Hiding SelectASourceVisible");
}
}
else
{
Debug.Console(1, "AvFunctionsDriver: CurrentSingleSourceChange Hiding SelectASourceVisible");
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
}
if (_CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && _CurrentRoom.CurrentSourceInfo != null)
TriList.StringInput[UIStringJoin.CallSharedSourceNameText].StringValue = _CurrentRoom.CurrentSourceInfo.PreferredName;
}
@@ -1147,17 +1339,16 @@ namespace PepperDash.Essentials
{
// 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
// CurrentRoom.ScheduleSource.GetSchedule();
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListIcon, "Calendar");
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListIcon, "Calendar");
TriList.SetString(UIStringJoin.MeetingsOrContactMethodListTitleText, "Today's Meetings");
ushort i = 0;
foreach (var m in CurrentRoom.ScheduleSource.CodecSchedule.Meetings)
{
i++;
MeetingOrContactMethodModalSrl.StringInputSig(i, 1).StringValue = m.StartTime.ToShortTimeString();
MeetingOrContactMethodModalSrl.StringInputSig(i, 2).StringValue = m.EndTime.ToShortTimeString();
MeetingOrContactMethodModalSrl.StringInputSig(i, 1).StringValue = m.StartTime.ToString("t", Global.Culture);
MeetingOrContactMethodModalSrl.StringInputSig(i, 2).StringValue = m.EndTime.ToString("t", Global.Culture);
MeetingOrContactMethodModalSrl.StringInputSig(i, 3).StringValue = m.Title;
MeetingOrContactMethodModalSrl.StringInputSig(i, 4).StringValue = string.Format("<br>{0}",m.Organizer);
MeetingOrContactMethodModalSrl.StringInputSig(i, 5).StringValue = "Join";
@@ -1202,12 +1393,12 @@ namespace PepperDash.Essentials
var value = _CurrentRoom.OnFeedback.BoolValue;
TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value;
//TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value;
if (value) //ON
{
SetupActivityFooterWhenRoomOn();
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
//TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = true;
}
@@ -1218,9 +1409,8 @@ namespace PepperDash.Essentials
VCDriver.Hide();
SetupActivityFooterWhenRoomOff();
ShowLogo();
SetActivityFooterFeedbacks();
TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
//TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = false;
//TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
// Clear this so that the pesky meeting warning can resurface every minute when off
LastMeetingDismissedId = null;
}
@@ -1455,6 +1645,8 @@ namespace PepperDash.Essentials
/// </summary>
void PrepareForCodecIncomingCall();
uint CallListOrMeetingInfoPopoverVisibilityJoin { get; }
SubpageReferenceList MeetingOrContactMethodModalSrl { get; }
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
@@ -14,6 +15,7 @@ using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
using PepperDash.Essentials.Devices.Common.Cameras;
namespace PepperDash.Essentials.UIDrivers.VC
@@ -83,6 +85,9 @@ namespace PepperDash.Essentials.UIDrivers.VC
StringBuilder SearchStringBuilder = new StringBuilder();
BoolFeedback SearchStringBackspaceVisibleFeedback;
StringFeedback PasswordStringFeedback;
StringBuilder PasswordStringBuilder = new StringBuilder();
ModalDialog IncomingCallModal;
eKeypadMode KeypadMode;
@@ -123,26 +128,24 @@ namespace PepperDash.Essentials.UIDrivers.VC
codec.CallStatusChange += new EventHandler<CodecCallStatusItemChangeEventArgs>(Codec_CallStatusChange);
// If the codec is ready, then get the values we want, otherwise wait
if (Codec.IsReady)
Codec_IsReady();
else
codec.IsReadyChange += (o, a) => Codec_IsReady();
//InCall = new BoolFeedback(() => false);
LocalPrivacyIsMuted = new BoolFeedback(() => false);
VCControlsInterlock = 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);
else
VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadVisible);
VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadVisible); */
StagingBarsInterlock = new JoinedSigInterlock(triList);
StagingBarsInterlock.SetButDontShow(UIBoolJoin.VCStagingInactivePopoverVisible);
if(Codec is IHasCallHistory)
StagingBarsInterlock.SetButDontShow(UIBoolJoin.VCStagingInactivePopoverWithRecentsVisible);
else
StagingBarsInterlock.SetButDontShow(UIBoolJoin.VCStagingInactivePopoverWithoutRecentsVisible);
StagingButtonsFeedbackInterlock = new JoinedSigInterlock(triList);
StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress);
@@ -150,7 +153,8 @@ namespace PepperDash.Essentials.UIDrivers.VC
// Return formatted when dialing, straight digits when in call
DialStringFeedback = new StringFeedback(() =>
{
if (KeypadMode == eKeypadMode.Dial)
// Format the number feedback if in dial mode and the codec is not IHasStartMeeting (ZoomRoom)
if (KeypadMode == eKeypadMode.Dial && !(Codec is IHasStartMeeting))
return GetFormattedDialString(DialStringBuilder.ToString());
else
return DialStringBuilder.ToString();
@@ -177,8 +181,22 @@ namespace PepperDash.Essentials.UIDrivers.VC
});
SearchStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.CodecDirectorySearchEntryText]);
SetupDirectoryList();
PasswordStringFeedback = new StringFeedback(() =>
{
if (PasswordStringBuilder.Length > 0)
{
Parent.Keyboard.EnableGoButton();
return PasswordStringBuilder.ToString();
}
else
{
Parent.Keyboard.DisableGoButton();
return "";
}
});
PasswordStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.PasswordPromptPasswordText]);
SetupDirectoryList();
SearchStringBackspaceVisibleFeedback = new BoolFeedback(() => SearchStringBuilder.Length > 0);
SearchStringBackspaceVisibleFeedback.LinkInputSig(triList.BooleanInput[UIBoolJoin.VCDirectoryBackspaceVisible]);
@@ -196,6 +214,18 @@ namespace PepperDash.Essentials.UIDrivers.VC
triList.SetSigHeldAction(UIBoolJoin.VCDirectoryBackspacePress, 500,
StartSearchBackspaceRepeat, StopSearchBackspaceRepeat, SearchKeypadBackspacePress);
if (Codec is IPasswordPrompt)
{
SetupPasswordPrompt();
}
// If the codec is ready, then get the values we want, otherwise wait
if (Codec.IsReady)
Codec_IsReady();
else
codec.IsReadyChange += (o, a) => Codec_IsReady();
}
catch (Exception e)
{
@@ -291,24 +321,20 @@ namespace PepperDash.Essentials.UIDrivers.VC
void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
var call = e.CallItem;
var meetingInfoSender = sender as IHasMeetingInfo;
switch (e.CallItem.Status)
{
case eCodecCallStatus.Connected:
// fire at SRL item
KeypadMode = eKeypadMode.DTMF;
DialStringBuilder.Remove(0, DialStringBuilder.Length);
DialStringFeedback.FireUpdate();
DialStringTextCheckEnables();
Parent.ShowNotificationRibbon("Connected", 2000);
StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress);
ShowKeypad();
((Parent.CurrentRoom as IHasCurrentVolumeControls).CurrentVolumeControls as IBasicVolumeWithFeedback).MuteOff();
OnCallConnected();
//VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCKeypadVisible);
break;
case eCodecCallStatus.Connecting:
// fire at SRL item
Parent.ShowNotificationRibbon("Connecting", 0);
OnCallConnected();
break;
case eCodecCallStatus.Dialing:
Parent.ShowNotificationRibbon("Connecting", 0);
@@ -324,7 +350,10 @@ namespace PepperDash.Essentials.UIDrivers.VC
DialStringBuilder.Remove(0, DialStringBuilder.Length);
DialStringFeedback.FireUpdate();
Parent.ShowNotificationRibbon("Disconnected", 2000);
Debug.Console(0, "Setting Connect Button mode to 0");
}
break;
case eCodecCallStatus.Disconnecting:
break;
@@ -345,16 +374,32 @@ namespace PepperDash.Essentials.UIDrivers.VC
ShowIncomingModal(call);
break;
}
default:
break;
}
TriList.UShortInput[UIUshortJoin.VCStagingConnectButtonMode].UShortValue = (ushort)(Codec.IsInCall ? 1 : 0);
uint stageJoin;
if (Codec.IsInCall)
stageJoin = UIBoolJoin.VCStagingActivePopoverVisible;
else
stageJoin = UIBoolJoin.VCStagingInactivePopoverVisible;
if (meetingInfoSender != null && Codec.IsInCall)
{
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)
stageJoin = UIBoolJoin.VCStagingActivePopoverVisible;
else
{
if (Codec is IHasCallHistory)
stageJoin = UIBoolJoin.VCStagingInactivePopoverWithRecentsVisible;
else
stageJoin = UIBoolJoin.VCStagingInactivePopoverWithoutRecentsVisible;
}
if (IsVisible)
StagingBarsInterlock.ShowInterlocked(stageJoin);
else
@@ -366,6 +411,36 @@ namespace PepperDash.Essentials.UIDrivers.VC
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>
/// Redraws the calls list on the header
/// </summary>
@@ -389,8 +464,8 @@ namespace PepperDash.Essentials.UIDrivers.VC
ActiveCallsSRL.Count = (ushort)activeList.Count;
// If Active Calls list is visible and codec is not in a call, hide the list
if (!Codec.IsInCall && Parent.PopupInterlock.CurrentJoin == UIBoolJoin.HeaderActiveCallsListVisible)
Parent.PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HeaderActiveCallsListVisible);
if (!Codec.IsInCall && Parent.PopupInterlock.CurrentJoin == Parent.CallListOrMeetingInfoPopoverVisibilityJoin)
Parent.PopupInterlock.ShowInterlockedWithToggle(Parent.CallListOrMeetingInfoPopoverVisibilityJoin);
}
/// <summary>
@@ -481,20 +556,67 @@ namespace PepperDash.Essentials.UIDrivers.VC
TriList.SetSigFalseAction(UIBoolJoin.VCStagingRecentsPress, ShowRecents);
TriList.SetSigFalseAction(UIBoolJoin.VCStagingCameraPress, ShowCameraControls);
TriList.SetSigFalseAction(UIBoolJoin.VCStagingConnectPress, ConnectPress);
TriList.SetSigFalseAction(UIBoolJoin.VCStagingMeetNowPress, MeetNowPress);
TriList.SetSigFalseAction(UIBoolJoin.CallStopSharingPress, CallStopSharingPress);
var meetingInfoCodec = Codec as IHasMeetingInfo;
TriList.SetSigFalseAction(UIBoolJoin.CallEndPress, () =>
{
if (Codec.ActiveCalls.Count > 1)
{
Parent.PopupInterlock.ShowInterlocked(UIBoolJoin.HeaderActiveCallsListVisible);
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
{
Codec.EndAllCalls();
}
});
TriList.SetSigFalseAction(UIBoolJoin.CallEndAllConfirmPress, () =>
{
Parent.PopupInterlock.HideAndClear();
Codec.EndAllCalls();
});
if (meetingInfoCodec != null)
{
TriList.SetSigFalseAction(UIBoolJoin.MeetingLeavePress, () =>
{
Parent.PopupInterlock.HideAndClear();
if (meetingInfoCodec.MeetingInfo.IsHost)
{
Codec.EndAllCalls();
}
else
{
var startMeetingCodec = Codec as IHasStartMeeting;
if (startMeetingCodec != null)
{
startMeetingCodec.LeaveMeeting();
}
}
});
}
}
void SetupCameraControls()
@@ -513,13 +635,18 @@ namespace PepperDash.Essentials.UIDrivers.VC
var codecOffCameras = Codec as IHasCameraOff;
var supportsCameraOffMode = Codec.SupportsCameraOff;
var codecAutoCameras = Codec as IHasCameraAutoMode;
if (codecAutoCameras != null)
var supportsAutoCameraMode = Codec.SupportsCameraAutoMode;
if (codecAutoCameras != null && supportsAutoCameraMode)
{
CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn());
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true;
codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]);
codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(TriList.BooleanInput[UIBoolJoin.VCCameraAutoModeIsOnFb]);
//TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 1 Pressed"].SetSigFalseAction(
//() => codecAutoCameras.CameraAutoModeOn());
@@ -554,7 +681,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
//TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 2 Pressed"].SetSigFalseAction(
// () => ShowCameraManualMode());
if (codecOffCameras != null)
if (codecOffCameras != null && supportsCameraOffMode)
{
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true;
codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]);
@@ -769,12 +896,14 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (camerasCodec != null && camerasCodec.SelectedCamera != null)
{
Debug.Console(2, "Attempting to map camera actions to selected camera: '{0}'", camerasCodec.SelectedCamera.Key);
var dpad = CameraPtzPad;
var camera = camerasCodec.SelectedCamera as IHasCameraPtzControl;
if (camera != null)
{
Debug.Console(2, "Selected camera is IHasCameraPtzControl");
if (camerasCodec.SelectedCamera.CanTilt)
{
dpad.SigUp.SetBoolSigAction((b) =>
@@ -839,25 +968,46 @@ namespace PepperDash.Essentials.UIDrivers.VC
}
}
else
{
Debug.Console(2, "Selected Camera is not IHasCameraPtzControl. No controls to map");
}
}
else
{
Debug.Console(2, "Codec does not have cameras of selected camera is null");
}
}
// Determines if codec is in manual camera control mode and shows feedback
void ShowCameraManualMode()
{
Debug.Console(2, "ShowCameraManualMode");
var inManualMode = true;
var codecOffCameras = Codec as IHasCameraOff;
var codecAutoCameras = Codec as IHasCameraAutoMode;
var supportsAutoCameras = codecAutoCameras != null && Codec.SupportsCameraAutoMode;
if (codecOffCameras != null && codecOffCameras.CameraIsOffFeedback.BoolValue)
{
inManualMode = false;
var codecCameraMute = Codec as IHasCameraMute;
if (codecCameraMute != null)
{
codecCameraMute.CameraMuteOff();
inManualMode = true;
}
}
// Clear auto mode
if (codecAutoCameras != null )
if (supportsAutoCameras)
{
if (codecAutoCameras.CameraAutoModeIsOnFeedback.BoolValue)
{
@@ -948,7 +1098,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
// if it's today, show a simpler string
string timeText = null;
if (c.StartTime.Date == DateTime.Now.Date)
timeText = c.StartTime.ToShortTimeString();
timeText = c.StartTime.ToString("t", Global.Culture);
else if (c.StartTime == DateTime.MinValue)
timeText = "";
else
@@ -1005,22 +1155,21 @@ namespace PepperDash.Essentials.UIDrivers.VC
void SetupDirectoryList()
{
var codec = Codec as IHasDirectory;
if (codec != null)
{
DirectoryList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCDirectoryList],
true, 1300);
codec.DirectoryResultReturned += new EventHandler<DirectoryEventArgs>(dir_DirectoryResultReturned);
if (codec == null)
{
return;
}
if (codec.PhonebookSyncState.InitialSyncComplete)
SetCurrentDirectoryToRoot();
else
{
codec.PhonebookSyncState.InitialSyncCompleted += new EventHandler<EventArgs>(PhonebookSyncState_InitialSyncCompleted);
}
DirectoryList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCDirectoryList],
true, 1300);
codec.DirectoryResultReturned += dir_DirectoryResultReturned;
RefreshDirectory();
}
if (codec.PhonebookSyncState.InitialSyncComplete)
SetCurrentDirectoryToRoot();
else
{
codec.PhonebookSyncState.InitialSyncCompleted += PhonebookSyncState_InitialSyncCompleted;
}
}
/// <summary>
@@ -1028,11 +1177,15 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// </summary>
void SetCurrentDirectoryToRoot()
{
(Codec as IHasDirectory).SetCurrentDirectoryToRoot();
var hasDirectory = Codec as IHasDirectory;
if (hasDirectory == null)
{
return;
}
hasDirectory.SetCurrentDirectoryToRoot();
SearchKeypadClear();
RefreshDirectory();
}
/// <summary>
@@ -1044,10 +1197,17 @@ namespace PepperDash.Essentials.UIDrivers.VC
{
var codec = Codec as IHasDirectory;
SetCurrentDirectoryToRoot();
if (codec == null)
{
return;
}
RefreshDirectory();
if (!codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue)
{
return;
}
SetCurrentDirectoryToRoot();
}
/// <summary>
@@ -1057,8 +1217,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// <param name="e"></param>
void dir_DirectoryResultReturned(object sender, DirectoryEventArgs e)
{
RefreshDirectory();
RefreshDirectory(e.Directory);
}
/// <summary>
@@ -1087,16 +1246,27 @@ namespace PepperDash.Essentials.UIDrivers.VC
}
/// <summary>
///
/// </summary>
/// <param name="dir"></param>
void RefreshDirectory()
/// <summary>
///
/// </summary>
void RefreshDirectory()
{
if ((Codec as IHasDirectory).CurrentDirectoryResult.CurrentDirectoryResults.Count > 0)
var codec = Codec as IHasDirectory;
if (codec == null)
{
return;
}
RefreshDirectory(codec.CurrentDirectoryResult);
}
void RefreshDirectory(CodecDirectory directory)
{
if (directory.CurrentDirectoryResults.Count > 0)
{
ushort i = 0;
foreach (var r in (Codec as IHasDirectory).CurrentDirectoryResult.CurrentDirectoryResults)
foreach (var r in directory.CurrentDirectoryResults)
{
if (i == DirectoryList.MaxCount)
{
@@ -1116,19 +1286,33 @@ namespace PepperDash.Essentials.UIDrivers.VC
// If more than one contact method, show contact method modal dialog
DirectoryList.SetItemButtonAction(i, b =>
{
if (!b)
if (b)
{
// Refresh the contact methods list
RefreshContactMethodsModalList(dc);
Parent.PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.MeetingsOrContacMethodsListVisible);
return;
}
// Refresh the contact methods list
RefreshContactMethodsModalList(dc);
Parent.PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.MeetingsOrContacMethodsListVisible);
});
}
else if (dc.ContactMethods.Count == 1)
{
var invitableContact = dc as IInvitableContact;
if (invitableContact != null)
{
DirectoryList.SetItemButtonAction(i, b => { if (!b) Codec.Dial(invitableContact); });
}
else
{
// If only one contact method, just dial that method
DirectoryList.SetItemButtonAction(i, b => { if (!b) Codec.Dial(dc.ContactMethods[0].Number); });
}
}
else
{
// If only one contact method, just dial that method
DirectoryList.SetItemButtonAction(i, b => { if (!b) Codec.Dial(dc.ContactMethods[0].Number); });
Debug.Console(1, "Unable to dial contact. No availble ContactMethod(s) specified");
}
}
else // is DirectoryFolder
@@ -1155,8 +1339,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
DirectoryList.SetItemMainText(1, "No Results Found");
}
}
}
void RefreshContactMethodsModalList(DirectoryContact contact)
{
@@ -1201,7 +1384,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
var lc = Codec as IHasCodecLayouts;
if (lc != null)
{
TriList.SetSigFalseAction(UIBoolJoin.VCLayoutTogglePress, lc.LocalLayoutToggleSingleProminent);
lc.LocalLayoutFeedback.LinkInputSig(TriList.StringInput[UIStringJoin.VCLayoutModeText]);
lc.LocalLayoutFeedback.OutputChange += (o,a) =>
{
@@ -1214,14 +1397,24 @@ namespace PepperDash.Essentials.UIDrivers.VC
var cisco = Codec as PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoSparkCodec;
if (cisco != null)
{
TriList.SetSigFalseAction(UIBoolJoin.VCLayoutTogglePress, lc.LocalLayoutToggleSingleProminent);
// Cisco has min/max buttons that need special sauce
cisco.SharingContentIsOnFeedback.OutputChange += CiscoSharingAndPresentation_OutputChanges;
//cisco.PresentationViewMaximizedFeedback.OutputChange += CiscoSharingAndPresentation_OutputChanges;
TriList.SetSigFalseAction(UIBoolJoin.VCMinMaxPress, cisco.MinMaxLayoutToggle);
}
var zoomRoom = Codec as PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom.ZoomRoom;
if (zoomRoom != null)
{
TriList.BooleanInput[UIBoolJoin.VCLayoutToggleEnable].BoolValue = true;
TriList.SetSigFalseAction(UIBoolJoin.VCLayoutTogglePress, lc.LocalLayoutToggle);
}
}
}
/// <summary>
@@ -1249,7 +1442,21 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// </summary>
void RevealKeyboard()
{
if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCKeypadWithFavoritesVisible && KeypadMode == eKeypadMode.Dial)
if (_passwordPromptDialogVisible)
{
Debug.Console(2, "Attaching Keyboard to PasswordPromptDialog");
DetachDialKeyboard();
DetachSearchKeyboard();
var kb = Parent.Keyboard;
kb.KeyPress -= Keyboard_PasswordKeyPress;
kb.KeyPress += Keyboard_PasswordKeyPress;
kb.HideAction = this.DetachPasswordKeyboard;
kb.GoButtonText = "Submit";
kb.GoButtonVisible = true;
PasswordStringCheckEnables();
kb.Show();
}
else if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCKeypadWithFavoritesVisible && KeypadMode == eKeypadMode.Dial)
{
var kb = Parent.Keyboard;
kb.KeyPress -= Keyboard_DialKeyPress;
@@ -1271,6 +1478,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
SearchStringKeypadCheckEnables();
kb.Show();
}
}
/// <summary>
@@ -1326,6 +1534,32 @@ namespace PepperDash.Essentials.UIDrivers.VC
}
}
/// <summary>
/// Event handler for keyboard dialing
/// </summary>
void Keyboard_PasswordKeyPress(object sender, PepperDash.Essentials.Core.Touchpanels.Keyboards.KeyboardControllerPressEventArgs e)
{
if (_passwordPromptDialogVisible)
{
if (e.Text != null)
PasswordStringBuilder.Append(e.Text);
else
{
if (e.SpecialKey == KeyboardSpecialKey.Backspace)
PasswordKeypadBackspacePress();
else if (e.SpecialKey == KeyboardSpecialKey.Clear)
PasswordKeypadClear();
else if (e.SpecialKey == KeyboardSpecialKey.GoButton)
{
(Codec as IPasswordPrompt).SubmitPassword(PasswordStringBuilder.ToString());
HidePasswordPrompt();
}
}
PasswordStringFeedback.FireUpdate();
PasswordStringCheckEnables();
}
}
/// <summary>
/// Call
/// </summary>
@@ -1339,6 +1573,11 @@ namespace PepperDash.Essentials.UIDrivers.VC
Parent.Keyboard.KeyPress -= Keyboard_SearchKeyPress;
}
void DetachPasswordKeyboard()
{
Parent.Keyboard.KeyPress -= Keyboard_PasswordKeyPress;
}
/// <summary>
/// Shows the camera controls subpage
/// </summary>
@@ -1416,6 +1655,22 @@ namespace PepperDash.Essentials.UIDrivers.VC
StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingRecentsPress);
}
/// <summary>
/// Meet Now button
/// </summary>
void MeetNowPress()
{
var startMeetingCodec = Codec as IHasStartMeeting;
if (startMeetingCodec != null)
{
startMeetingCodec.StartMeeting(startMeetingCodec.DefaultMeetingDurationMin);
}
else
{
Debug.Console(2, "Codce does not implment IHasStartMeeting. Cannot meet now");
}
}
/// <summary>
/// Connect call button
/// </summary>
@@ -1426,6 +1681,16 @@ namespace PepperDash.Essentials.UIDrivers.VC
Codec.Dial(DialStringBuilder.ToString());
}
/// <summary>
/// Stop Sharing button
/// </summary>
void CallStopSharingPress()
{
Codec.StopSharing();
Parent.CurrentRoom.RunRouteAction("codecOsd", Parent.CurrentRoom.SourceListKey);
}
/// <summary>
///
/// </summary>
@@ -1592,6 +1857,40 @@ namespace PepperDash.Essentials.UIDrivers.VC
Parent.Keyboard.DisableGoButton();
}
/// <summary>
/// Clears the Password keypad
/// </summary>
void PasswordKeypadClear()
{
PasswordStringBuilder.Remove(0, PasswordStringBuilder.Length);
PasswordStringFeedback.FireUpdate();
PasswordStringCheckEnables();
}
/// <summary>
///
/// </summary>
void PasswordKeypadBackspacePress()
{
PasswordStringBuilder.Remove(PasswordStringBuilder.Length - 1, 1);
PasswordStringFeedback.FireUpdate();
PasswordStringCheckEnables();
}
/// <summary>
/// Checks the enabled states of various elements around the keypad
/// </summary>
void PasswordStringCheckEnables()
{
var textIsEntered = PasswordStringBuilder.Length > 0;
if (textIsEntered)
Parent.Keyboard.EnableGoButton();
else
Parent.Keyboard.DisableGoButton();
}
/// <summary>
/// Returns the text value for the keypad dial entry field
@@ -1637,5 +1936,62 @@ namespace PepperDash.Essentials.UIDrivers.VC
Dial = 0,
DTMF
}
void SetupPasswordPrompt()
{
var passwordPromptCodec = Codec as IPasswordPrompt;
passwordPromptCodec.PasswordRequired += new EventHandler<PasswordPromptEventArgs>(passwordPromptCodec_PasswordRequired);
TriList.SetSigFalseAction(UIBoolJoin.PasswordPromptCancelPress, HidePasswordPrompt);
TriList.SetSigFalseAction(UIBoolJoin.PasswordPromptTextPress, RevealKeyboard);
}
void passwordPromptCodec_PasswordRequired(object sender, PasswordPromptEventArgs e)
{
if (e.LoginAttemptCancelled)
{
HidePasswordPrompt();
return;
}
if (!string.IsNullOrEmpty(e.Message))
{
TriList.SetString(UIStringJoin.PasswordPromptMessageText, e.Message);
}
if (e.LoginAttemptFailed)
{
// TODO: Show a message modal to indicate the login attempt failed
return;
}
TriList.SetBool(UIBoolJoin.PasswordPromptErrorVisible, e.LastAttemptWasIncorrect);
ShowPasswordPrompt();
}
private bool _passwordPromptDialogVisible;
void ShowPasswordPrompt()
{
// Clear out any previous data
PasswordKeypadClear();
_passwordPromptDialogVisible = true;
TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible);
RevealKeyboard();
}
void HidePasswordPrompt()
{
if (_passwordPromptDialogVisible)
{
_passwordPromptDialogVisible = false;
Parent.Keyboard.Hide();
TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible);
PasswordKeypadClear();
}
}
}
}

View File

@@ -8,11 +8,19 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
/// </summary>
public interface IMobileControl : IKeyed
{
void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent);
void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent);
void LinkSystemMonitorToAppServer();
}
/// <summary>
/// Describes a MobileSystemController that accepts IEssentialsRoom
/// </summary>
public interface IMobileControl3 : IMobileControl
{
void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent);
}
/// <summary>
/// Describes a MobileControl Room Bridge
/// </summary>

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Describes the functionality required to prompt a user to enter a password
/// </summary>
public interface IPasswordPrompt
{
/// <summary>
/// Notifies when a password is required or is entered incorrectly
/// </summary>
event EventHandler<PasswordPromptEventArgs> PasswordRequired;
/// <summary>
/// Submits the password
/// </summary>
/// <param name="password"></param>
void SubmitPassword(string password);
}
public class PasswordPromptEventArgs : EventArgs
{
/// <summary>
/// Indicates if the last submitted password was incorrect
/// </summary>
public bool LastAttemptWasIncorrect { get; private set; }
/// <summary>
/// Indicates that the login attempt has failed
/// </summary>
public bool LoginAttemptFailed { get; private set; }
/// <summary>
/// Indicates that the process was cancelled and the prompt should be dismissed
/// </summary>
public bool LoginAttemptCancelled { get; private set; }
/// <summary>
/// A message to be displayed to the user
/// </summary>
public string Message { get; private set; }
public PasswordPromptEventArgs(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message)
{
LastAttemptWasIncorrect = lastAttemptIncorrect;
LoginAttemptFailed = loginFailed;
LoginAttemptCancelled = loginCancelled;
Message = message;
}
}
}

View File

@@ -19,13 +19,34 @@ namespace PepperDash.Essentials.Core
protected EssentialsDevice(string key)
: base(key)
{
SubscribeToActivateComplete();
}
protected EssentialsDevice(string key, string name)
: base(key, name)
{
SubscribeToActivateComplete();
}
private void SubscribeToActivateComplete()
{
DeviceManager.AllDevicesActivated += DeviceManagerOnAllDevicesActivated;
}
private void DeviceManagerOnAllDevicesActivated(object sender, EventArgs eventArgs)
{
CrestronInvoke.BeginInvoke((o) =>
{
try
{
Initialize();
}
catch (Exception ex)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Exception initializing device: {0}", ex.Message);
Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.StackTrace);
}
});
}
}

View File

@@ -1,90 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.GeneralIO;
using Crestron.SimplSharp.Reflection;
using PepperDash.Core;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.CrestronIO;
using PepperDash.Essentials.Core.Touchpanels;
namespace PepperDash.Essentials.Core
{
public class DeviceFactoryWrapper
{
public CType CType { get; set; }
public string Description { get; set; }
public Func<DeviceConfig, IKeyed> FactoryMethod { get; set; }
public DeviceFactoryWrapper()
{
CType = null;
Description = "Not Available";
}
}
public class DeviceFactory
{
public DeviceFactory()
{
var assy = Assembly.GetExecutingAssembly();
PluginLoader.SetEssentialsAssembly(assy.GetName().Name, assy);
var types = assy.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract);
if (types != null)
{
foreach (var type in types)
{
try
{
var factory = (IDeviceFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(type);
factory.LoadTypeFactories();
}
catch (Exception e)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to load type: '{1}' DeviceFactory: {0}", e, type.Name);
}
}
}
}
/// <summary>
/// A dictionary of factory methods, keyed by config types, added by plugins.
/// These methods are looked up and called by GetDevice in this class.
/// </summary>
static Dictionary<string, DeviceFactoryWrapper> FactoryMethods =
new Dictionary<string, DeviceFactoryWrapper>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Adds a plugin factory method
/// </summary>
/// <param name="dc"></param>
/// <returns></returns>
public static void AddFactoryForType(string typeName, Func<DeviceConfig, IKeyed> method)
{
Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName);
DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = 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);
if(FactoryMethods.ContainsKey(typeName))
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to add type: '{0}'. Already exists in DeviceFactory", typeName);
return;
}
var wrapper = new DeviceFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method };
DeviceFactory.FactoryMethods.Add(typeName, wrapper);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.GeneralIO;
using Crestron.SimplSharp.Reflection;
using PepperDash.Core;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.CrestronIO;
using PepperDash.Essentials.Core.Touchpanels;
namespace PepperDash.Essentials.Core
{
public class DeviceFactoryWrapper
{
public CType CType { get; set; }
public string Description { get; set; }
public Func<DeviceConfig, IKeyed> FactoryMethod { get; set; }
public DeviceFactoryWrapper()
{
CType = null;
Description = "Not Available";
}
}
public class DeviceFactory
{
public DeviceFactory()
{
var assy = Assembly.GetExecutingAssembly();
PluginLoader.SetEssentialsAssembly(assy.GetName().Name, assy);
var types = assy.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract);
if (types != null)
{
foreach (var type in types)
{
try
{
var factory = (IDeviceFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(type);
factory.LoadTypeFactories();
}
catch (Exception e)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to load type: '{1}' DeviceFactory: {0}", e, type.Name);
}
}
}
}
/// <summary>
/// A dictionary of factory methods, keyed by config types, added by plugins.
/// These methods are looked up and called by GetDevice in this class.
/// </summary>
static Dictionary<string, DeviceFactoryWrapper> FactoryMethods =
new Dictionary<string, DeviceFactoryWrapper>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Adds a plugin factory method
/// </summary>
/// <param name="dc"></param>
/// <returns></returns>
public static void AddFactoryForType(string typeName, Func<DeviceConfig, IKeyed> method)
{
Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName);
DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = 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);
if(FactoryMethods.ContainsKey(typeName))
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to add type: '{0}'. Already exists in DeviceFactory", typeName);
return;
}
var wrapper = new DeviceFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method };
DeviceFactory.FactoryMethods.Add(typeName, wrapper);
}
private static void CheckForSecrets(IEnumerable<JProperty> obj)
@@ -156,44 +156,53 @@ namespace PepperDash.Essentials.Core
Debug.Console(0, Debug.ErrorLogLevel.Error, "Exception occurred while creating device {0}: {1}", dc.Key, ex.Message);
Debug.Console(2, "{0}", ex.StackTrace);
if (ex.InnerException == null)
{
return null;
}
Debug.Console(0, Debug.ErrorLogLevel.Error, "Inner exception while creating device {0}: {1}", dc.Key,
ex.InnerException.Message);
Debug.Console(2, "{0}", ex.InnerException.StackTrace);
return null;
}
}
/// <summary>
/// Prints the type names and associated metadata from the FactoryMethods collection.
/// </summary>
/// <param name="command"></param>
public static void GetDeviceFactoryTypes(string filter)
{
Dictionary<string, DeviceFactoryWrapper> types = new Dictionary<string, DeviceFactoryWrapper>();
if (!string.IsNullOrEmpty(filter))
{
types = FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value);
}
else
{
types = FactoryMethods;
}
Debug.Console(0, "Device Types:");
foreach (var type in types.OrderBy(t => t.Key))
{
var description = type.Value.Description;
var cType = "Not Specified by Plugin";
if(type.Value.CType != null)
{
cType = type.Value.CType.FullName;
}
Debug.Console(0,
@"Type: '{0}'
CType: '{1}'
Description: {2}", type.Key, cType, description);
}
}
}
/// <summary>
/// Prints the type names and associated metadata from the FactoryMethods collection.
/// </summary>
/// <param name="command"></param>
public static void GetDeviceFactoryTypes(string filter)
{
Dictionary<string, DeviceFactoryWrapper> types = new Dictionary<string, DeviceFactoryWrapper>();
if (!string.IsNullOrEmpty(filter))
{
types = FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value);
}
else
{
types = FactoryMethods;
}
Debug.Console(0, "Device Types:");
foreach (var type in types.OrderBy(t => t.Key))
{
var description = type.Value.Description;
var cType = "Not Specified by Plugin";
if(type.Value.CType != null)
{
cType = type.Value.CType.FullName;
}
Debug.Console(0,
@"Type: '{0}'
CType: '{1}'
Description: {2}", type.Key, cType, description);
}
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Text.RegularExpressions;
using System.Globalization;
using Crestron.SimplSharp;
using System.Collections.Generic;
using Crestron.SimplSharp.CrestronIO;
@@ -28,6 +29,10 @@ namespace PepperDash.Essentials.Core
public static eCrestronSeries ProcessorSeries { get { return CrestronEnvironment.ProgramCompatibility; } }
// TODO: consider making this configurable later
public static IFormatProvider Culture = CultureInfo.CreateSpecificCulture("en-US");
/// <summary>
/// The file path prefix to the folder containing configuration files
/// </summary>

View File

@@ -88,11 +88,6 @@ namespace PepperDash.Essentials.Core.Privacy
else
Debug.Console(0, this, "Unable to add Red LED device");
DeviceManager.AllDevicesActivated += (o, a) =>
{
CheckPrivacyMode();
};
AddPostActivationAction(() => {
PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange;
PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange;
@@ -103,6 +98,15 @@ namespace PepperDash.Essentials.Core.Privacy
return base.CustomActivate();
}
#region Overrides of Device
public override void Initialize()
{
CheckPrivacyMode();
}
#endregion
public void SetPrivacyDevice(IPrivacy privacyDevice)
{
PrivacyDevice = privacyDevice;

View File

@@ -126,6 +126,7 @@ namespace PepperDash.Essentials.Core
public void SetEnableState(bool state)
{
Debug.Console(2, this, "Sensor is {0}, SetEnableState: {1}", _partitionSensor == null ? "null" : "not null", state);
if (_partitionSensor == null)
return;
@@ -134,6 +135,7 @@ namespace PepperDash.Essentials.Core
public void IncreaseSensitivity()
{
Debug.Console(2, this, "Sensor is {0}, IncreaseSensitivity", _partitionSensor == null ? "null" : "not null");
if (_partitionSensor == null)
return;
@@ -142,6 +144,7 @@ namespace PepperDash.Essentials.Core
public void DecreaseSensitivity()
{
Debug.Console(2, this, "Sensor is {0}, DecreaseSensitivity", _partitionSensor == null ? "null" : "not null");
if (_partitionSensor == null)
return;
@@ -150,6 +153,7 @@ namespace PepperDash.Essentials.Core
public void SetSensitivity(ushort value)
{
Debug.Console(2, this, "Sensor is {0}, SetSensitivity: {1}", _partitionSensor == null ? "null" : "not null", value);
if (_partitionSensor == null)
return;
@@ -177,8 +181,7 @@ namespace PepperDash.Essentials.Core
Debug.Console(0, this, "Linking to Bridge Type {0}", GetType().Name);
// link input from simpl
trilist.SetSigTrueAction(joinMap.Enable.JoinNumber, () => SetEnableState(true));
trilist.SetSigFalseAction(joinMap.Enable.JoinNumber, () => SetEnableState(false));
trilist.SetBoolSigAction(joinMap.Enable.JoinNumber, SetEnableState);
trilist.SetSigTrueAction(joinMap.IncreaseSensitivity.JoinNumber, IncreaseSensitivity);
trilist.SetSigTrueAction(joinMap.DecreaseSensitivity.JoinNumber, DecreaseSensitivity);
trilist.SetUShortSigAction(joinMap.Sensitivity.JoinNumber, SetSensitivity);

View File

@@ -203,6 +203,7 @@
<Compile Include="Devices\PC\Laptop.cs" />
<Compile Include="Devices\ReconfigurableDevice.cs" />
<Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" />
<Compile Include="DeviceTypeInterfaces\IPasswordPrompt.cs" />
<Compile Include="DeviceTypeInterfaces\ITvPresetsProvider.cs" />
<Compile Include="DeviceTypeInterfaces\LanguageLabel.cs" />
<Compile Include="DeviceTypeInterfaces\ILanguageProvider.cs" />

View File

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

View File

@@ -15,7 +15,7 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// Describes the basic functionality of an EssentialsRoom
/// </summary>
public interface IEssentialsRoom : IKeyName, IReconfigurableDevice
public interface IEssentialsRoom : IKeyName, IReconfigurableDevice, IRunDefaultPresentRoute
{
BoolFeedback OnFeedback { get; }
@@ -56,7 +56,6 @@ namespace PepperDash.Essentials.Core
void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes);
void PowerOnToDefaultOrLastSource();
bool RunDefaultPresentRoute();
void SetDefaultLevels();

View File

@@ -8,6 +8,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Cards;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpProInternal;
using Newtonsoft.Json;
using PepperDash.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>
@@ -497,166 +516,189 @@ namespace PepperDash.Essentials.DM
{
case "dmchd":
{
var inputCard = new DmcHd(number, this.Chassis);
var cecPort = inputCard.HdmiInput as ICec;
AddHdmiInCardPorts(number, cecPort);
var inputCard = new DmcHd(number, Chassis);
AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
}
break;
case "dmchddsp":
{
var inputCard = new DmcHdDsp(number, this.Chassis);
var cecPort = inputCard.HdmiInput as ICec;
AddHdmiInCardPorts(number, cecPort);
var inputCard = new DmcHdDsp(number, Chassis);
AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
}
break;
case "dmc4khd":
{
var inputCard = new Dmc4kHd(number, this.Chassis);
var cecPort = inputCard.HdmiInput as ICec;
AddHdmiInCardPorts(number, cecPort);
var inputCard = new Dmc4kHd(number, Chassis);
AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
}
break;
case "dmc4khddsp":
{
var inputCard = new Dmc4kHdDsp(number, this.Chassis);
var cecPort = inputCard.HdmiInput as ICec;
AddHdmiInCardPorts(number, cecPort);
var inputCard = new Dmc4kHdDsp(number, Chassis);
AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
}
break;
case "dmc4kzhd":
{
var inputCard = new Dmc4kzHd(number, this.Chassis);
var cecPort = inputCard.HdmiInput as ICec;
AddHdmiInCardPorts(number, cecPort);
}
var inputCard = new Dmc4kzHd(number, Chassis);
AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
break;
}
case "dmc4kzhddsp":
{
var inputCard = new Dmc4kzHdDsp(number, this.Chassis);
var cecPort = inputCard.HdmiInput as ICec;
AddHdmiInCardPorts(number, cecPort);
}
var inputCard = new Dmc4kzHdDsp(number, Chassis);
AddHdmiInCardPorts(number, inputCard.HdmiInput, inputCard.HdmiInput);
break;
}
case "dmcc":
{
var inputCard = new DmcC(number, this.Chassis);
var cecPort = inputCard.DmInput as ICec;
AddDmInCardPorts(number, cecPort);
var inputCard = new DmcC(number, Chassis);
//DmInput doesn't implement ICec...cast was resulting in null anyway
AddDmInCardPorts(number, null, inputCard.DmInput);
}
break;
case "dmccdsp":
{
var inputCard = new DmcCDsp(number, this.Chassis);
var cecPort = inputCard.DmInput as ICec;
AddDmInCardPorts(number, cecPort);
}
var inputCard = new DmcCDsp(number, Chassis);
//DmInput doesn't implement ICec...cast was resulting in null anyway
AddDmInCardPorts(number, null, inputCard.DmInput);
break;
}
case "dmc4kc":
{
var inputCard = new Dmc4kC(number, this.Chassis);
var cecPort = inputCard.DmInput as ICec;
AddDmInCardPorts(number, cecPort);
}
var inputCard = new Dmc4kC(number, Chassis);
AddDmInCardPorts(number, inputCard.DmInput,inputCard.DmInput);
break;
}
case "dmc4kcdsp":
{
var inputCard = new Dmc4kCDsp(number, this.Chassis);
var cecPort = inputCard.DmInput as ICec;
AddDmInCardPorts(number, cecPort);
}
var inputCard = new Dmc4kCDsp(number, Chassis);
AddDmInCardPorts(number, inputCard.DmInput,inputCard.DmInput);
break;
}
case "dmc4kzc":
{
var inputCard = new Dmc4kzC(number, this.Chassis);
var cecPort = inputCard.DmInput as ICec;
AddDmInCardPorts(number, cecPort);
}
var inputCard = new Dmc4kzC(number, Chassis);
AddDmInCardPorts(number, inputCard.DmInput,inputCard.DmInput);
break;
}
case "dmc4kzcdsp":
{
var inputCard = new Dmc4kzCDsp(number, this.Chassis);
var cecPort = inputCard.DmInput as ICec;
AddDmInCardPorts(number, cecPort);
var inputCard = new Dmc4kzCDsp(number, Chassis);
AddDmInCardPorts(number, inputCard.DmInput, inputCard.DmInput);
break;
}
break;
case "dmccat":
new DmcCat(number, this.Chassis);
AddDmInCardPorts(number);
{
var inputCard = new DmcCat(number, Chassis);
AddDmInCardPorts(number, null, inputCard.DmInput);
break;
}
case "dmccatdsp":
new DmcCatDsp(number, this.Chassis);
AddDmInCardPorts(number);
{
var inputCard = new DmcCatDsp(number, Chassis);
AddDmInCardPorts(number, null, inputCard.DmInput);
break;
}
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);
break;
}
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);
break;
}
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);
break;
}
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);
break;
}
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,
eRoutingPortConnectionType.Sdi, null);
AddInCardHdmiAndAudioLoopPorts(number);
break;
}
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);
AddInCardHdmiLoopPort(number);
break;
}
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);
AddInCardHdmiLoopPort(number);
break;
}
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);
AddInCardHdmiLoopPort(number);
break;
}
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);
AddInCardHdmiLoopPort(number);
break;
}
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);
AddInCardHdmiLoopPort(number);
break;
}
case "dmcvid4":
new DmcVid4(number, Chassis);
{
var inputCard = new DmcVid4(number, Chassis);
AddInputPortWithDebug(number, "compositeIn1", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite);
AddInputPortWithDebug(number, "compositeIn2", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite);
AddInputPortWithDebug(number, "compositeIn3", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite);
AddInputPortWithDebug(number, "compositeIn4", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite);
AddInCardHdmiLoopPort(number);
break;
}
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);
break;
}
}
}
@@ -672,12 +714,24 @@ namespace PepperDash.Essentials.DM
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)
{
AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort);
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)
{
AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video,
@@ -816,20 +870,55 @@ namespace PepperDash.Essentials.DM
/// </summary>
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>
/// 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>
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);
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)
inputPort.Port = cecPort;
@@ -989,6 +1078,23 @@ namespace PepperDash.Essentials.DM
Debug.Console(2, this, "No index of {0} found in InputStreamCardStateFeedbacks");
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:
{
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.
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))
{
@@ -1077,7 +1183,7 @@ namespace PepperDash.Essentials.DM
var inputNumber = Chassis.Outputs[output].AudioOutFeedback == null ? 0 : Chassis.
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))
{
@@ -1179,7 +1285,10 @@ namespace PepperDash.Essentials.DM
var output = outputSelector as DMOutput;
if (output == null)
var isUsbInput = (sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput;
var isUsbOutput = (sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput;
if (output == null && !(isUsbOutput || isUsbInput))
{
Debug.Console(0, this, Debug.ErrorLogLevel.Warning,
"Unable to execute switch for inputSelector {0} to outputSelector {1}", inputSelector,
@@ -1210,7 +1319,10 @@ namespace PepperDash.Essentials.DM
if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
{
Chassis.VideoEnter.BoolValue = true;
output.VideoOut = input; //Chassis.Outputs[output].VideoOut = inCard;
if (output != null)
{
output.VideoOut = input; //Chassis.Outputs[output].VideoOut = inCard;
}
}
if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)
@@ -1220,17 +1332,66 @@ namespace PepperDash.Essentials.DM
{
dmMdMnxn.AudioEnter.BoolValue = true;
}
output.AudioOut = input;
//Chassis.Outputs[output].AudioOut = inCard;
if (output != null)
{
output.AudioOut = input;
}
}
if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput || (sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput)
if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput)
{
Chassis.USBEnter.BoolValue = true;
output.USBRoutedTo = input;
Chassis.USBEnter.BoolValue = true;
if (inputSelector == null && output != null)
{
//clearing the route is intended
output.USBRoutedTo = null;
return;
}
if (inputSelector != null && input == null)
{
//input selector is DMOutput...we're doing a out to out route
var tempInput = inputSelector as DMOutput;
if (tempInput == null || output == null)
{
return;
}
output.USBRoutedTo = tempInput;
return;
}
if (input != null & output != null)
{
output.USBRoutedTo = input;
}
}
if((sigType & eRoutingSignalType.UsbInput) != eRoutingSignalType.UsbInput)
{
return;
}
Chassis.USBEnter.BoolValue = true;
if (output != null)
{
output.USBRoutedTo = input;
return;
}
var tempOutput = outputSelector as DMInput;
if (tempOutput == null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Warning,
"Unable to execute switch for inputSelector {0} to outputSelector {1}", inputSelector,
outputSelector);
return;
}
tempOutput.USBRoutedTo = input;
}
#endregion
#region IRoutingNumeric Members
@@ -1243,8 +1404,10 @@ namespace PepperDash.Essentials.DM
DMInputOutputBase dmCard;
//Routing Input to Input or Output to Input
if ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput)
{
Debug.Console(2, this, "Executing USB Input switch.\r\n in:{0} output: {1}", inputSelector, outputSelector);
if (outputSelector > chassisSize)
{
uint outputIndex;
@@ -1264,13 +1427,14 @@ namespace PepperDash.Essentials.DM
dmCard = Chassis.Inputs[inputSelector];
}
ExecuteSwitch(dmCard, Chassis.Outputs[outputSelector], sigType);
ExecuteSwitch(dmCard, Chassis.Inputs[outputSelector], sigType);
return;
}
if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput)
{
Debug.Console(2, this, "Executing USB Output switch.\r\n in:{0} output: {1}", inputSelector, outputSelector);
//routing Output to Output or Input to Output
if (inputSelector > chassisSize)
{
//wanting to route an output to an output. Subtract chassis size and get output, unless it's 8x8
@@ -1388,6 +1552,16 @@ namespace PepperDash.Essentials.DM
{
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)
@@ -1428,6 +1602,13 @@ namespace PepperDash.Essentials.DM
InputStreamCardStateFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[join]);
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)
@@ -1564,10 +1745,19 @@ namespace PepperDash.Essentials.DM
{
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,
uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter)
uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter)
{
var transmitter = basicTransmitter as DmTxControllerBase;
if (transmitter == null) return;
@@ -1581,7 +1771,9 @@ namespace PepperDash.Essentials.DM
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)
{
@@ -1614,6 +1806,19 @@ namespace PepperDash.Essentials.DM
trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue =
(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,
@@ -1896,15 +2101,15 @@ namespace PepperDash.Essentials.DM
{
var props = JsonConvert.DeserializeObject
<PepperDash.Essentials.DM.Config.DMChassisPropertiesConfig>(dc.Properties.ToString());
return PepperDash.Essentials.DM.DmChassisController.
<DMChassisPropertiesConfig>(dc.Properties.ToString());
return DmChassisController.
GetDmChassisController(dc.Key, dc.Name, type, props);
}
else if (type.StartsWith("dmmd128x") || type.StartsWith("dmmd64x"))
{
var props = JsonConvert.DeserializeObject
<PepperDash.Essentials.DM.Config.DMChassisPropertiesConfig>(dc.Properties.ToString());
return PepperDash.Essentials.DM.DmBladeChassisController.
<DMChassisPropertiesConfig>(dc.Properties.ToString());
return DmBladeChassisController.
GetDmChassisController(dc.Key, dc.Name, type, props);
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
@@ -15,421 +16,489 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.DM.Chassis
{
[Description("Wrapper class for all HdMdNxM4E switchers")]
public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback
{
private HdMdNxM _Chassis;
private HdMd4x14kE _Chassis4x1;
[Description("Wrapper class for all HdMdNxM4E switchers")]
public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback
{
private HdMdNxM _Chassis;
private HdMd4x14kE _Chassis4x1;
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
public Dictionary<uint, string> InputNames { get; set; }
public Dictionary<uint, string> OutputNames { get; set; }
public Dictionary<uint, string> InputNames { get; set; }
public Dictionary<uint, string> OutputNames { get; set; }
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
public FeedbackCollection<BoolFeedback> VideoInputSyncFeedbacks { get; private set; }
public FeedbackCollection<IntFeedback> VideoOutputRouteFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> InputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputRouteNameFeedbacks { get; private set; }
public FeedbackCollection<BoolFeedback> InputHdcpEnableFeedback { get; private set; }
public FeedbackCollection<StringFeedback> DeviceNameFeedback { get; private set; }
public FeedbackCollection<BoolFeedback> AutoRouteFeedback { get; private set; }
public FeedbackCollection<BoolFeedback> VideoInputSyncFeedbacks { get; private set; }
public FeedbackCollection<IntFeedback> VideoOutputRouteFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> InputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputRouteNameFeedbacks { get; private set; }
public FeedbackCollection<BoolFeedback> InputHdcpEnableFeedback { get; private set; }
public StringFeedback DeviceNameFeedback { get; private set; }
public BoolFeedback AutoRouteFeedback { get; private set; }
#region Constructor
#region Constructor
public HdMdNxM4kEBridgeableController(string key, string name, HdMdNxM chassis,
HdMdNxM4kEBridgeablePropertiesConfig props)
: base(key, name, chassis)
{
_Chassis = chassis;
var _props = props;
public HdMdNxM4kEBridgeableController(string key, string name, HdMdNxM chassis,
HdMdNxM4kEBridgeablePropertiesConfig props)
: base(key, name, chassis)
{
_Chassis = chassis;
Name = name;
InputNames = props.Inputs;
OutputNames = props.Outputs;
if (props == null)
{
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>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
if (props.Inputs != null)
{
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)
{
_Chassis4x1 = _Chassis as HdMd4x14kE;
AutoRouteFeedback.Add(new BoolFeedback(this.Name + "-" + InputNames[1], () => _Chassis4x1.AutoModeOnFeedback.BoolValue));
}
VideoInputSyncFeedbacks = new FeedbackCollection<BoolFeedback>();
VideoOutputRouteFeedbacks = new FeedbackCollection<IntFeedback>();
InputNameFeedbacks = new FeedbackCollection<StringFeedback>();
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++)
{
var index = i;
var inputName = InputNames[index];
_Chassis.Inputs[index].Name.StringValue = inputName;
if (_Chassis.NumberOfInputs == 1)
{
_Chassis4x1 = _Chassis as HdMd4x14kE;
AutoRouteFeedback = new BoolFeedback(() => _Chassis4x1.AutoModeOnFeedback.BoolValue);
}
InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, index, this)
{
FeedbackMatchObject = _Chassis.HdmiInputs[index]
});
VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue));
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.NumberOfInputs; i++)
{
var index = i;
var inputName = InputNames[index];
//_Chassis.Inputs[index].Name.StringValue = inputName;
_Chassis.HdmiInputs[index].Name.StringValue = inputName;
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
var index = i;
var outputName = OutputNames[index];
_Chassis.Outputs[i].Name.StringValue = outputName;
InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, _Chassis.HdmiInputs[index], this)
{
FeedbackMatchObject = _Chassis.HdmiInputs[index]
});
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,
eRoutingPortConnectionType.Hdmi, index, this)
{
FeedbackMatchObject = _Chassis.HdmiOutputs[index]
});
VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[index].VideoOutFeedback.Number));
OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].Name.StringValue));
OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue));
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
var index = i;
var outputName = OutputNames[index];
//_Chassis.Outputs[index].Name.StringValue = outputName;
//_Chassis.HdmiOutputs[index].Name.StringValue = outputName;
_Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange);
_Chassis.DMOutputChange += new DMOutputEventHandler(Chassis_DMOutputChange);
OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo,
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>
/// 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);
}
#region Methods
public void EnableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
/// <summary>
/// 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);
}
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOn();
InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
}
public void EnableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
public void DisableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOn();
InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
}
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOff();
InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
}
public void DisableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
public void EnableAutoRoute()
{
if (_Chassis.NumberOfInputs != 1) return;
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOff();
InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
}
if (_Chassis4x1 == null) return;
public void EnableAutoRoute()
{
if (_Chassis.NumberOfInputs != 1) return;
_Chassis4x1.AutoModeOn();
}
if (_Chassis4x1 == null) return;
public void DisableAutoRoute()
{
if (_Chassis.NumberOfInputs != 1) return;
_Chassis4x1.AutoModeOn();
}
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()
{
AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback);
AddCollectionsToList(VideoOutputRouteFeedbacks);
AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks, DeviceNameFeedback);
}
#region PostActivate
#endregion
public void AddFeedbackCollections()
{
AddFeedbackToList(DeviceNameFeedback);
AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback);
AddCollectionsToList(VideoOutputRouteFeedbacks);
AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks);
}
#region FeedbackCollection Methods
#endregion
//Add arrays of collections
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);
}
}
}
#region FeedbackCollection Methods
public void AddCollectionsToList(params FeedbackCollection<StringFeedback>[] newFbs)
{
foreach (FeedbackCollection<StringFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
//Add arrays of collections
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);
}
}
}
//Add Collections
public void AddCollectionToList(FeedbackCollection<BoolFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
public void AddCollectionsToList(params FeedbackCollection<StringFeedback>[] newFbs)
{
foreach (FeedbackCollection<StringFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
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)
{
foreach (var f in newFbs)
{
if (f == null) continue;
AddFeedbackToList(f);
}
}
AddFeedbackToList(f);
}
}
public void AddCollectionToList(FeedbackCollection<IntFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
public void AddCollectionToList(FeedbackCollection<StringFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
AddFeedbackToList(f);
}
}
AddFeedbackToList(f);
}
}
public void AddCollectionToList(FeedbackCollection<StringFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
//Add Individual Feedbacks
public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback newFb)
{
if (newFb == null) return;
AddFeedbackToList(f);
}
}
if (!Feedbacks.Contains(newFb))
{
Feedbacks.Add(newFb);
}
}
//Add Individual Feedbacks
public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback 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)
{
// 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];
}
#region IRouting Members
#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)
{
ExecuteSwitch(inputSelector, outputSelector, signalType);
}
// Try to make switch only when necessary. The unit appears to toggle when already selected.
var current = output.VideoOut;
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)
{
var joinMap = new HdMdNxM4kEControllerJoinMap(joinStart);
Debug.Console(2, this, "ExecuteNumericSwitch: input={0} output={1}", input, output);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
ExecuteSwitch(input, output, signalType);
}
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<HdMdNxM4kEControllerJoinMap>(joinMapSerialized);
#endregion
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.");
}
#endregion
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
DeviceNameFeedback[this.Name].LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]);
#region Bridge Linking
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)
{
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]);
}
AutoRouteFeedback.FireUpdate();
}
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
var joinIndex = i - 1;
//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));
void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
{
if (args.EventId != DMOutputEventIds.VideoOutEventId) return;
//Serial
InputNameFeedbacks[InputNames[i]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]);
}
var output = args.Number;
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
var joinIndex = i - 1;
//Analog
VideoOutputRouteFeedbacks[OutputNames[i]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]);
trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteSwitch(a, i, eRoutingSignalType.AudioVideo));
var inputNumber = _Chassis.HdmiOutputs[output].VideoOutFeedback == null
? 0
: _Chassis.HdmiOutputs[output].VideoOutFeedback.Number;
//Serial
OutputNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]);
OutputRouteNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]);
}
var outputName = OutputNames[output];
_Chassis.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler(Chassis_OnlineStatusChange);
var feedback = VideoOutputRouteFeedbacks[outputName];
trilist.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler((d, args) =>
{
if (args.DeviceOnLine)
{
foreach (var feedback in Feedbacks)
if (feedback == null)
{
return;
}
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.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DM;
using Newtonsoft.Json;
@@ -13,6 +14,7 @@ using PepperDash.Essentials.DM.Config;
namespace PepperDash.Essentials.DM.Chassis
{
[Obsolete("Please use HdMdNxM4kEBridgeable Controller")]
public class HdMdNxM4kEController : CrestronGenericBaseDevice, IRoutingInputsOutputs, IRouting
{
public HdMdNxM Chassis { get; private set; }
@@ -31,6 +33,7 @@ namespace PepperDash.Essentials.DM.Chassis
HdMdNxM4kEPropertiesConfig props)
: base(key, name, chassis)
{
Debug.Console(0, this, "Type hdmd4x14ke is obsolete. Please use hdmd4x14ke-bridgeable");
Chassis = chassis;
// logical ports
@@ -43,14 +46,19 @@ namespace PepperDash.Essentials.DM.Chassis
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
OutputPorts.Add(new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this));
// physical settings
if (props != null && props.Inputs != null)
{
var inputRegex = new Regex(@"(?<InputNum>\d)", RegexOptions.IgnoreCase);
foreach (var kvp in props.Inputs)
{
// strip "hdmiIn"
var inputNum = Convert.ToUInt32(kvp.Key.Substring(6));
// get numnbers from key and convert to int
//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;
// set hdcp disables

View File

@@ -1,40 +1,40 @@
using Crestron.SimplSharpPro;
using System;
using System.Linq;
//using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.DM
{
using eVst = eX02VideoSourceType;
using Crestron.SimplSharpPro;
using System;
using System.Linq;
//using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.DM
{
using eVst = eX02VideoSourceType;
using eAst = eX02AudioSourceType;
public class DmTx4kz202CController : DmTxControllerBase, ITxRoutingWithFeedback,
IIROutputPorts, IComPorts
{
public DmTx4kz202C Tx { get; private set; }
public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; }
public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; }
public RoutingOutputPort DmOut { get; private set; }
public RoutingOutputPort HdmiLoopOut { get; private set; }
public override StringFeedback ActiveVideoInputFeedback { get; protected set; }
public IntFeedback VideoSourceNumericFeedback { get; protected set; }
public IntFeedback AudioSourceNumericFeedback { get; protected set; }
public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; }
public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; }
public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; }
public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
//public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
public class DmTx4kz202CController : DmTxControllerBase, ITxRoutingWithFeedback,
IIROutputPorts, IComPorts
{
public DmTx4kz202C Tx { get; private set; }
public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; }
public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; }
public RoutingOutputPort DmOut { get; private set; }
public RoutingOutputPort HdmiLoopOut { get; private set; }
public override StringFeedback ActiveVideoInputFeedback { get; protected set; }
public IntFeedback VideoSourceNumericFeedback { get; protected set; }
public IntFeedback AudioSourceNumericFeedback { get; protected set; }
public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; }
public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; }
public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; }
public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
//public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
//public override ushort HdcpSupportCapability { get; protected set; }
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
@@ -47,48 +47,48 @@ namespace PepperDash.Essentials.DM
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
/// <summary>
/// Helps get the "real" inputs, including when in Auto
/// </summary>
public eX02VideoSourceType ActualActiveVideoInput
{
get
{
if (Tx.VideoSourceFeedback != eVst.Auto)
return Tx.VideoSourceFeedback;
if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
return eVst.Hdmi1;
return Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue ? eVst.Hdmi2 : eVst.AllDisabled;
}
}
public RoutingPortCollection<RoutingInputPort> InputPorts
{
get
{
return new RoutingPortCollection<RoutingInputPort>
{
HdmiIn1,
HdmiIn2,
AnyVideoInput
};
}
}
public RoutingPortCollection<RoutingOutputPort> OutputPorts
{
get
{
return new RoutingPortCollection<RoutingOutputPort> { DmOut, HdmiLoopOut };
}
}
public DmTx4kz202CController(string key, string name, DmTx4kz202C tx)
: base(key, name, tx)
{
}
/// <summary>
/// Helps get the "real" inputs, including when in Auto
/// </summary>
public eX02VideoSourceType ActualActiveVideoInput
{
get
{
if (Tx.VideoSourceFeedback != eVst.Auto)
return Tx.VideoSourceFeedback;
if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
return eVst.Hdmi1;
return Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue ? eVst.Hdmi2 : eVst.AllDisabled;
}
}
public RoutingPortCollection<RoutingInputPort> InputPorts
{
get
{
return new RoutingPortCollection<RoutingInputPort>
{
HdmiIn1,
HdmiIn2,
AnyVideoInput
};
}
}
public RoutingPortCollection<RoutingOutputPort> OutputPorts
{
get
{
return new RoutingPortCollection<RoutingOutputPort> { DmOut, HdmiLoopOut };
}
}
public DmTx4kz202CController(string key, string name, DmTx4kz202C tx)
: base(key, name, tx)
{
Tx = tx;
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
@@ -104,208 +104,208 @@ namespace PepperDash.Essentials.DM
FeedbackMatchObject = eVst.Hdmi2
};
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
Tx.BaseEvent += Tx_BaseEvent;
Tx.OnlineStatusChange += Tx_OnlineStatusChange;
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
//Return VideoSourceFeedback here as DM-TX-4KZ-202-C does not support audio breakaway
AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback);
HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpStateFeedback =
new IntFeedback(
() =>
tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback
? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback
: (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue);
var combinedFuncs = new VideoStatusFuncsWrapper
{
HdcpActiveFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue),
HdcpStateFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString();
return "";
},
VideoResolutionFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
return "";
},
VideoSyncFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
};
AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs);
DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.DmCat, null, this);
HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback,
Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback);
// Set Ports for CEC
HdmiIn1.Port = Tx.HdmiInputs[1];
HdmiIn2.Port = Tx.HdmiInputs[2];
HdmiLoopOut.Port = Tx.HdmiOutput;
DmOut.Port = Tx.DmOutput;
}
public override bool CustomActivate()
{
// Link up all of these damned events to the various RoutingPorts via a helper handler
Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId);
Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId);
Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId);
Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId);
// Base does register and sets up comm monitoring.
return base.CustomActivate();
}
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = GetDmTxJoinMap(joinStart, joinMapKey);
if (Hdmi1VideoSyncFeedback != null)
{
Hdmi1VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input1VideoSyncStatus.JoinNumber]);
}
if (Hdmi2VideoSyncFeedback != null)
{
Hdmi2VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input2VideoSyncStatus.JoinNumber]);
}
LinkDmTxToApi(this, trilist, joinMap, bridge);
}
public void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type)
{
Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input);
switch (type)
{
case eRoutingSignalType.Video:
switch (input)
{
case 0:
{
ExecuteSwitch(eVst.Auto, null, type);
break;
}
case 1:
{
ExecuteSwitch(HdmiIn1.Selector, null, type);
break;
}
case 2:
{
ExecuteSwitch(HdmiIn2.Selector, null, type);
break;
}
case 3:
{
ExecuteSwitch(eVst.AllDisabled, null, type);
break;
}
}
break;
case eRoutingSignalType.Audio:
switch (input)
{
case 0:
{
ExecuteSwitch(eAst.Auto, null, type);
break;
}
case 1:
{
ExecuteSwitch(eAst.Hdmi1, null, type);
break;
}
case 2:
{
ExecuteSwitch(eAst.Hdmi2, null, type);
break;
}
case 3:
{
ExecuteSwitch(eAst.AllDisabled, null, type);
break;
}
}
break;
}
}
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
{
if ((signalType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
Tx.VideoSource = (eVst)inputSelector;
if(((signalType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio))
Debug.Console(2, this, "Unable to execute audio-only switch for tx {0}", Key);
}
void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString());
switch (args.EventId)
{
case EndpointInputStreamEventIds.HdcpSupportOffFeedbackEventId:
case EndpointInputStreamEventIds.HdcpSupportOnFeedbackEventId:
case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId:
if (inputStream == Tx.HdmiInputs[1]) HdmiIn1HdcpCapabilityFeedback.FireUpdate();
if (inputStream == Tx.HdmiInputs[2]) HdmiIn2HdcpCapabilityFeedback.FireUpdate();
break;
case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId:
if (inputStream == Tx.HdmiInputs[1]) Hdmi1VideoSyncFeedback.FireUpdate();
if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
break;
}
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
Tx.BaseEvent += Tx_BaseEvent;
Tx.OnlineStatusChange += Tx_OnlineStatusChange;
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
//Return VideoSourceFeedback here as DM-TX-4KZ-202-C does not support audio breakaway
AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback);
HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpStateFeedback =
new IntFeedback(
() =>
tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback
? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback
: (int)tx.HdmiInputs[2].HdcpCapabilityFeedback);
HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue);
var combinedFuncs = new VideoStatusFuncsWrapper
{
HdcpActiveFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue),
HdcpStateFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString();
return "";
},
VideoResolutionFeedbackFunc = () =>
{
if (ActualActiveVideoInput == eVst.Hdmi1)
return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
if (ActualActiveVideoInput == eVst.Hdmi2)
return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
return "";
},
VideoSyncFeedbackFunc = () =>
(ActualActiveVideoInput == eVst.Hdmi1
&& tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
|| (ActualActiveVideoInput == eVst.Hdmi2
&& tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue)
};
AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs);
DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.DmCat, null, this);
HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback,
Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback);
// Set Ports for CEC
HdmiIn1.Port = Tx.HdmiInputs[1];
HdmiIn2.Port = Tx.HdmiInputs[2];
HdmiLoopOut.Port = Tx.HdmiOutput;
DmOut.Port = Tx.DmOutput;
}
public override bool CustomActivate()
{
// Link up all of these damned events to the various RoutingPorts via a helper handler
Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId);
Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId);
Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId);
Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId);
// Base does register and sets up comm monitoring.
return base.CustomActivate();
}
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = GetDmTxJoinMap(joinStart, joinMapKey);
if (Hdmi1VideoSyncFeedback != null)
{
Hdmi1VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input1VideoSyncStatus.JoinNumber]);
}
if (Hdmi2VideoSyncFeedback != null)
{
Hdmi2VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Input2VideoSyncStatus.JoinNumber]);
}
LinkDmTxToApi(this, trilist, joinMap, bridge);
}
public void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type)
{
Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input);
switch (type)
{
case eRoutingSignalType.Video:
switch (input)
{
case 0:
{
ExecuteSwitch(eVst.Auto, null, type);
break;
}
case 1:
{
ExecuteSwitch(HdmiIn1.Selector, null, type);
break;
}
case 2:
{
ExecuteSwitch(HdmiIn2.Selector, null, type);
break;
}
case 3:
{
ExecuteSwitch(eVst.AllDisabled, null, type);
break;
}
}
break;
case eRoutingSignalType.Audio:
switch (input)
{
case 0:
{
ExecuteSwitch(eAst.Auto, null, type);
break;
}
case 1:
{
ExecuteSwitch(eAst.Hdmi1, null, type);
break;
}
case 2:
{
ExecuteSwitch(eAst.Hdmi2, null, type);
break;
}
case 3:
{
ExecuteSwitch(eAst.AllDisabled, null, type);
break;
}
}
break;
}
}
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
{
if ((signalType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
Tx.VideoSource = (eVst)inputSelector;
if(((signalType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio))
Debug.Console(2, this, "Unable to execute audio-only switch for tx {0}", Key);
}
void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString());
switch (args.EventId)
{
case EndpointInputStreamEventIds.HdcpSupportOffFeedbackEventId:
case EndpointInputStreamEventIds.HdcpSupportOnFeedbackEventId:
case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId:
if (inputStream == Tx.HdmiInputs[1]) HdmiIn1HdcpCapabilityFeedback.FireUpdate();
if (inputStream == Tx.HdmiInputs[2]) HdmiIn2HdcpCapabilityFeedback.FireUpdate();
break;
case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId:
if (inputStream == Tx.HdmiInputs[1]) Hdmi1VideoSyncFeedback.FireUpdate();
if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
break;
}
}
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
@@ -313,7 +313,7 @@ namespace PepperDash.Essentials.DM
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
@@ -338,68 +338,68 @@ namespace PepperDash.Essentials.DM
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
var localInputAudioPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.VideoSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}
/// <summary>
/// Relays the input stream change to the appropriate RoutingInputPort.
/// </summary>
void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
{
if (eventId != EndpointInputStreamEventIds.SyncDetectedFeedbackEventId)
{
return;
}
inputPort.VideoStatus.VideoSyncFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate();
}
/// <summary>
/// Relays the VideoAttributes change to a RoutingInputPort
/// </summary>
void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
{
//// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds
//Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}",
// args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType());
switch (eventId)
{
case VideoAttributeEventIds.HdcpActiveFeedbackEventId:
inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate();
AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate();
break;
case VideoAttributeEventIds.HdcpStateFeedbackEventId:
inputPort.VideoStatus.HdcpStateFeedback.FireUpdate();
AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate();
break;
case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId:
case VideoAttributeEventIds.VerticalResolutionFeedbackEventId:
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
break;
case VideoAttributeEventIds.FramesPerSecondFeedbackEventId:
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
break;
}
}
#region IIROutputPorts Members
public CrestronCollection<IROutputPort> IROutputPorts { get { return Tx.IROutputPorts; } }
public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } }
#endregion
#region IComPorts Members
public CrestronCollection<ComPort> ComPorts { get { return Tx.ComPorts; } }
public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } }
#endregion
}
}
/// <summary>
/// Relays the input stream change to the appropriate RoutingInputPort.
/// </summary>
void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
{
if (eventId != EndpointInputStreamEventIds.SyncDetectedFeedbackEventId)
{
return;
}
inputPort.VideoStatus.VideoSyncFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate();
}
/// <summary>
/// Relays the VideoAttributes change to a RoutingInputPort
/// </summary>
void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId)
{
//// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds
//Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}",
// args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType());
switch (eventId)
{
case VideoAttributeEventIds.HdcpActiveFeedbackEventId:
inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate();
AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate();
break;
case VideoAttributeEventIds.HdcpStateFeedbackEventId:
inputPort.VideoStatus.HdcpStateFeedback.FireUpdate();
AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate();
break;
case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId:
case VideoAttributeEventIds.VerticalResolutionFeedbackEventId:
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
break;
case VideoAttributeEventIds.FramesPerSecondFeedbackEventId:
inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate();
AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate();
break;
}
}
#region IIROutputPorts Members
public CrestronCollection<IROutputPort> IROutputPorts { get { return Tx.IROutputPorts; } }
public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } }
#endregion
#region IComPorts Members
public CrestronCollection<ComPort> ComPorts { get { return Tx.ComPorts; } }
public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } }
#endregion
}
}

View File

@@ -339,7 +339,7 @@ namespace PepperDash.Essentials.DM
var localVideoInputPort =
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
var localAudioInputPort =
InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
@@ -364,8 +364,8 @@ namespace PepperDash.Essentials.DM
OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
var localInputAudioPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.VideoSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;

View File

@@ -11,10 +11,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
/// <summary>
/// For rooms that have audio codec
/// </summary>
public interface IHasAudioCodec
public interface IHasAudioCodec:IHasInCallFeedback
{
AudioCodecBase AudioCodec { get; }
BoolFeedback InCallFeedback { get; }
///// <summary>
///// Make this more specific

View File

@@ -69,6 +69,22 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("directoryResults")]
public List<DirectoryItem> CurrentDirectoryResults { get; private set; }
public List<DirectoryItem> Contacts
{
get
{
return CurrentDirectoryResults.OfType<DirectoryContact>().Cast<DirectoryItem>().ToList();
}
}
public List<DirectoryItem> Folders
{
get
{
return CurrentDirectoryResults.OfType<DirectoryFolder>().Cast<DirectoryItem>().ToList();
}
}
/// <summary>
/// Used to store the ID of the current folder for CurrentDirectoryResults
/// </summary>
@@ -104,6 +120,15 @@ namespace PepperDash.Essentials.Devices.Common.Codec
SortDirectory();
}
/// <summary>
/// Filters the CurrentDirectoryResults by the predicate
/// </summary>
/// <param name="predicate"></param>
public void FilterContacts(Func<DirectoryItem, bool> predicate)
{
CurrentDirectoryResults = CurrentDirectoryResults.Where(predicate).ToList();
}
/// <summary>
/// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically
/// </summary>
@@ -135,7 +160,19 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public interface IInvitableContact
{
bool IsInvitableContact { get; }
}
public class InvitableDirectoryContact : DirectoryContact, IInvitableContact
{
[JsonProperty("isInvitableContact")]
public bool IsInvitableContact
{
get
{
return this is IInvitableContact;
}
}
}
/// <summary>
@@ -184,8 +221,6 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("contactMethods")]
public List<ContactMethod> ContactMethods { get; set; }

View File

@@ -235,6 +235,15 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{
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

View File

@@ -1,17 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Displays
{
public interface IInputHdmi1 { void InputHdmi1(); }
public interface IInputHdmi2 { void InputHdmi2(); }
public interface IInputHdmi3 { void InputHdmi3(); }
public interface IInputHdmi4 { void InputHdmi4(); }
public interface IInputDisplayPort1 { void InputDisplayPort1(); }
public interface IInputDisplayPort2 { void InputDisplayPort2(); }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Displays
{
public interface IInputHdmi1 { void InputHdmi1(); }
public interface IInputHdmi2 { void InputHdmi2(); }
public interface IInputHdmi3 { void InputHdmi3(); }
public interface IInputHdmi4 { void InputHdmi4(); }
public interface IInputDisplayPort1 { void InputDisplayPort1(); }
public interface IInputDisplayPort2 { void InputDisplayPort2(); }
public interface IInputVga1 { void InputVga1(); }
}

View File

@@ -120,9 +120,12 @@
<Compile Include="VideoCodec\CiscoCodec\RoomPresets.cs" />
<Compile Include="Cameras\CameraControl.cs" />
<Compile Include="Display\PanasonicThDisplay.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingInfo.cs" />
<Compile Include="VideoCodec\Interfaces\IHasParticipants.cs" />
<Compile Include="VideoCodec\Interfaces\IHasPresentationOnlyMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewSize.cs" />
<Compile Include="VideoCodec\Interfaces\IHasStartMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\iVideoCodecInfo.cs" />
<Compile Include="Codec\iHasCallFavorites.cs" />
<Compile Include="Codec\iHasCallHistory.cs" />

View File

@@ -314,7 +314,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
FarEndIsSharingContentFeedback = new BoolFeedback(FarEndIsSharingContentFeedbackFunc);
CameraIsOffFeedback = new BoolFeedback(() => CodecStatus.Status.Video.Input.MainVideoMute.BoolValue);
CameraIsMutedFeedback = CameraIsOffFeedback;
SupportsCameraOff = true;
PresentationViewMaximizedFeedback = new BoolFeedback(() => CurrentPresentationView == "Maximized");
@@ -417,6 +417,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CodecStatus.Status.RoomAnalytics.PeoplePresence.ValueChangedAction = RoomIsOccupiedFeedback.FireUpdate;
CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate;
CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = CameraAutoModeIsOnFeedback.FireUpdate;
CodecStatus.Status.Cameras.SpeakerTrack.Availability.ValueChangedAction = () => { SupportsCameraAutoMode = CodecStatus.Status.Cameras.SpeakerTrack.Availability.BoolValue; };
CodecStatus.Status.Video.Selfview.Mode.ValueChangedAction = SelfviewIsOnFeedback.FireUpdate;
CodecStatus.Status.Video.Selfview.PIPPosition.ValueChangedAction = ComputeSelfviewPipStatus;
CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout;
@@ -550,6 +551,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CrestronConsole.AddNewConsoleCommand(GetPhonebook, "GetCodecPhonebook", "Triggers a refresh of the codec phonebook", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(GetBookings, "GetCodecBookings", "Triggers a refresh of the booking data for today", ConsoleAccessLevelEnum.AccessOperator);
return base.CustomActivate();
}
#region Overrides of Device
public override void Initialize()
{
var socket = Communication as ISocketStatus;
if (socket != null)
{
@@ -558,9 +566,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
Communication.Connect();
CommunicationMonitor.Start();
CommunicationMonitor.Start();
string prefix = "xFeedback register ";
const string prefix = "xFeedback register ";
CliFeedbackRegistrationExpression =
prefix + "/Configuration" + Delimiter +
@@ -575,14 +583,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
prefix + "/Status/Video/Layout" + Delimiter +
prefix + "/Status/Video/Input/MainVideoMute" + Delimiter +
prefix + "/Bookings" + Delimiter +
prefix + "/Event/CallDisconnect" + Delimiter +
prefix + "/Event/CallDisconnect" + Delimiter +
prefix + "/Event/Bookings" + Delimiter +
prefix + "/Event/CameraPresetListUpdated" + Delimiter +
prefix + "/Event/UserInterface/Presentation/ExternalSource/Selected/SourceIdentifier" + Delimiter;
return base.CustomActivate();
prefix + "/Event/UserInterface/Presentation/ExternalSource/Selected/SourceIdentifier" + Delimiter;
}
#endregion
/// <summary>
/// Fires when initial codec sync is completed. Used to then send commands to get call history, phonebook, bookings, etc.
/// </summary>
@@ -735,6 +743,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
/// <summary>
/// Appends the delimiter and send the command to the codec
/// </summary>
/// <param name="command"></param>
public void SendText(string command)
{
if (CommDebuggingIsOn)

View File

@@ -277,9 +277,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public SoftwareID SoftwareID { get; set; }
}
public class Availability
public class Availability : ValueProperty
{
public string Value { get; set; }
string _Value;
public bool BoolValue { get; private set; }
public string Value
{
get
{
return _Value;
}
set
{
// If the incoming value is "Available" it sets the BoolValue true, otherwise sets it false
_Value = value;
BoolValue = value == "Available";
OnValueChanged();
}
}
}
public class Status2 : ValueProperty
@@ -311,6 +327,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public SpeakerTrack()
{
Status = new Status2();
Availability = new Availability();
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
/// <summary>
/// Describes a device that provides meeting information (like a ZoomRoom)
/// </summary>
public interface IHasMeetingInfo
{
event EventHandler<MeetingInfoEventArgs> MeetingInfoChanged;
MeetingInfo MeetingInfo { get; }
}
/// <summary>
/// Represents the information about a meeting in progress
/// Currently used for Zoom meetings
/// </summary>
public class MeetingInfo
{
[JsonProperty("id")]
public string Id { get; private set; }
[JsonProperty("name")]
public string Name { get; private set; }
[JsonProperty("host")]
public string Host { get; private set; }
[JsonProperty("password")]
public string Password { get; private set; }
[JsonProperty("shareStatus")]
public string ShareStatus { get; private set; }
[JsonProperty("isHost")]
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, bool isSharingMeeting, bool waitingForHost)
{
Id = id;
Name = name;
Host = host;
Password = password;
ShareStatus = shareStatus;
IsHost = isHost;
IsSharingMeeting = isSharingMeeting;
WaitingForHost = waitingForHost;
}
}
public class MeetingInfoEventArgs : EventArgs
{
public MeetingInfo Info { get; private set; }
public MeetingInfoEventArgs(MeetingInfo info)
{
Info = info;
}
}
}

View File

@@ -1,100 +1,112 @@
using System;
using System.Linq;
using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
/// <summary>
/// Describes a device that has call participants
/// </summary>
public interface IHasParticipants
{
CodecParticipants Participants { get; }
}
/// <summary>
/// Describes a device that has call participants
/// </summary>
public interface IHasParticipants
{
CodecParticipants Participants { get; }
}
/// <summary>
/// Describes the ability to mute and unmute a participant's video in a meeting
/// </summary>
public interface IHasParticipantVideoMute:IHasParticipants
{
void MuteVideoForParticipant(int userId);
void UnmuteVideoForParticipant(int userId);
void ToggleVideoForParticipant(int userId);
}
/// <summary>
/// Describes the ability to mute and unmute a participant's video in a meeting
/// </summary>
public interface IHasParticipantVideoMute : IHasParticipants
{
void MuteVideoForParticipant(int userId);
void UnmuteVideoForParticipant(int userId);
void ToggleVideoForParticipant(int userId);
}
/// <summary>
/// Describes the ability to mute and unmute a participant's audio in a meeting
/// </summary>
public interface IHasParticipantAudioMute : IHasParticipantVideoMute
{
void MuteAudioForParticipant(int userId);
void UnmuteAudioForParticipant(int userId);
void ToggleAudioForParticipant(int userId);
}
/// <summary>
/// Describes the ability to mute and unmute a participant's audio in a meeting
/// </summary>
public interface IHasParticipantAudioMute : IHasParticipantVideoMute
{
void MuteAudioForParticipant(int userId);
void UnmuteAudioForParticipant(int userId);
void ToggleAudioForParticipant(int userId);
}
/// <summary>
/// Describes the ability to pin and unpin a participant in a meeting
/// </summary>
public interface IHasParticipantPinUnpin : IHasParticipants
{
IntFeedback NumberOfScreensFeedback { get; }
int ScreenIndexToPinUserTo { get; }
/// <summary>
/// Describes the ability to pin and unpin a participant in a meeting
/// </summary>
public interface IHasParticipantPinUnpin : IHasParticipants
{
IntFeedback NumberOfScreensFeedback { get; }
int ScreenIndexToPinUserTo { get; }
void PinParticipant(int userId, int screenIndex);
void UnPinParticipant(int userId);
void ToggleParticipantPinState(int userId, int screenIndex);
}
void PinParticipant(int userId, int screenIndex);
void UnPinParticipant(int userId);
void ToggleParticipantPinState(int userId, int screenIndex);
}
public class CodecParticipants
{
private List<Participant> _currentParticipants;
public List<Participant> CurrentParticipants {
get { return _currentParticipants; }
set
public class CodecParticipants
{
private List<Participant> _currentParticipants;
public List<Participant> CurrentParticipants
{
get { return _currentParticipants; }
set
{
_currentParticipants = value;
OnParticipantsChanged();
}
}
public Participant Host
{
get
{
_currentParticipants = value;
OnParticipantsChanged();
return _currentParticipants.FirstOrDefault(p => p.IsHost);
}
}
public event EventHandler<EventArgs> ParticipantsListHasChanged;
public event EventHandler<EventArgs> ParticipantsListHasChanged;
public CodecParticipants()
{
_currentParticipants = new List<Participant>();
}
public CodecParticipants()
{
_currentParticipants = new List<Participant>();
}
public void OnParticipantsChanged()
{
var handler = ParticipantsListHasChanged;
public void OnParticipantsChanged()
{
var handler = ParticipantsListHasChanged;
if (handler == null) return;
if (handler == null) return;
handler(this, new EventArgs());
}
}
handler(this, new EventArgs());
}
}
/// <summary>
/// Represents a call participant
/// </summary>
public class Participant
{
public int UserId { get; set; }
public bool IsHost { get; set; }
public string Name { get; set; }
public bool CanMuteVideo { get; set; }
public bool CanUnmuteVideo { get; set; }
public bool VideoMuteFb { get; set; }
public bool AudioMuteFb { get; set; }
public bool HandIsRaisedFb { get; set; }
public bool IsPinnedFb { get; set; }
public int ScreenIndexIsPinnedToFb { get; set; }
/// <summary>
/// Represents a call participant
/// </summary>
public class Participant
{
public int UserId { get; set; }
public bool IsHost { get; set; }
public bool IsMyself { get; set; }
public string Name { get; set; }
public bool CanMuteVideo { get; set; }
public bool CanUnmuteVideo { get; set; }
public bool VideoMuteFb { get; set; }
public bool AudioMuteFb { get; set; }
public bool HandIsRaisedFb { get; set; }
public bool IsPinnedFb { get; set; }
public int ScreenIndexIsPinnedToFb { get; set; }
public Participant()
{
// Initialize to -1 (no screen)
ScreenIndexIsPinnedToFb = -1;
}
}
public Participant()
{
// Initialize to -1 (no screen)
ScreenIndexIsPinnedToFb = -1;
}
}
}

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,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
/// <summary>
/// Describes the ability to start an ad-hoc meeting
/// </summary>
public interface IHasStartMeeting
{
/// <summary>
/// The default meeting duration in minutes
/// </summary>
uint DefaultMeetingDurationMin { get; }
/// <summary>
/// Start an ad-hoc meeting for the specified duration
/// </summary>
/// <param name="duration"></param>
void StartMeeting(uint duration);
/// <summary>
/// Leaves a meeting without ending it
/// </summary>
void LeaveMeeting();
}
}

View File

@@ -11,10 +11,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// <summary>
/// For rooms that have video codec
/// </summary>
public interface IHasVideoCodec
public interface IHasVideoCodec:IHasInCallFeedback,IPrivacy
{
VideoCodecBase VideoCodec { get; }
BoolFeedback InCallFeedback { get; }
///// <summary>
///// Make this more specific
@@ -26,11 +25,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary>
IntFeedback CallTypeFeedback { get; }
/// <summary>
///
/// </summary>
BoolFeedback PrivacyModeIsOnFeedback { get; }
/// <summary>
/// When something in the room is sharing with the far end or through other means
/// </summary>

View File

@@ -78,6 +78,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
SetupCameras();
CreateOsdSource();
SetIsReady();
}
@@ -117,6 +119,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
}
bool _StandbyIsOn;
/// <summary>
/// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input
/// to enable routing
/// </summary>
private void CreateOsdSource()
{
OsdSource = new DummyRoutingInputsDevice(Key + "[osd]");
DeviceManager.AddDevice(OsdSource);
var tl = new TieLine(OsdSource.AudioVideoOutputPort, CodecOsdIn);
TieLineCollection.Default.Add(tl);
//foreach(var input in Status.Video.
}
/// <summary>
/// Dials, yo!
@@ -567,6 +582,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
void SetupCameras()
{
SupportsCameraAutoMode = true;
SupportsCameraOff = false;
Cameras = new List<CameraBase>();
var internalCamera = new MockVCCamera(Key + "-camera1", "Near End", this);

View File

@@ -65,8 +65,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public bool ShowSelfViewByDefault { get; protected set; }
protected bool SupportsCameraOff;
protected bool SupportsCameraAutoMode;
public bool SupportsCameraOff { get; protected set; }
public bool SupportsCameraAutoMode { get; protected set; }
public bool IsReady { get; protected set; }
@@ -298,6 +298,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
}
LinkVideoCodecToApi(codec, trilist, joinMap);
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC");
};
}
/// <summary>
@@ -785,6 +792,16 @@ ScreenIndexIsPinnedTo: {8} (a{17})
_currentMeetings = codec.CodecSchedule.Meetings.Where(m => m.StartTime >= currentTime || m.EndTime >= currentTime).ToList();
if (_currentMeetings.Count == 0)
{
var emptyXSigByteArray = XSigHelpers.ClearOutputs();
var emptyXSigString = Encoding.GetEncoding(XSigEncoding)
.GetString(emptyXSigByteArray, 0, emptyXSigByteArray.Length);
trilist.SetString(joinMap.Schedule.JoinNumber, emptyXSigString);
return;
}
var meetingsData = UpdateMeetingsListXSig(_currentMeetings);
trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData);
trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count);
@@ -836,10 +853,10 @@ ScreenIndexIsPinnedTo: {8} (a{17})
//serials
tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer);
tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title);
tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToShortDateString());
tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToShortTimeString());
tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToShortDateString());
tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToShortTimeString());
tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString("t", Global.Culture));
tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString("t", Global.Culture));
tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString("t", Global.Culture));
tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString("t", Global.Culture));
tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id);

View File

@@ -59,6 +59,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public List<zStatus.AudioVideoInputOutputLineItem> AudioOuputs { get; set; }
public List<zStatus.AudioVideoInputOutputLineItem> Cameras { get; set; }
public zEvent.PhoneCallStatus PhoneCall { get; set; }
public zEvent.NeedWaitForHost NeedWaitForHost { get; set; }
public ZoomRoomStatus()
{
@@ -76,6 +77,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
AudioOuputs = new List<zStatus.AudioVideoInputOutputLineItem>();
Cameras = new List<zStatus.AudioVideoInputOutputLineItem>();
PhoneCall = new zEvent.PhoneCallStatus();
NeedWaitForHost = new zEvent.NeedWaitForHost();
}
}
@@ -236,14 +238,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
/// <summary>
/// Used to be able to inplement IInvitableContact on DirectoryContact
/// </summary>
public class ZoomDirectoryContact : DirectoryContact, IInvitableContact
{
}
public class Phonebook
{
[JsonProperty("Contacts")]
@@ -276,6 +270,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (zoomRooms.Count > 0)
{
// If so, setup a rooms and contacts folder and add them.
directory.ResultsFolderId = "root";
roomFolder.Name = "Rooms";
roomFolder.ParentFolderId = "root";
roomFolder.FolderId = "rooms";
@@ -292,22 +289,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
try
{
if (zoomContacts.Count == 0) return directory;
if (zoomContacts.Count == 0)
{
return directory;
}
foreach (Contact c in zoomContacts)
{
foreach (Contact c in zoomContacts)
var contact = new InvitableDirectoryContact { Name = c.ScreenName, ContactId = c.Jid };
contact.ContactMethods.Add(new ContactMethod() { Number = c.Jid, Device = eContactMethodDevice.Video, CallType = eContactMethodCallType.Video, ContactMethodId = c.Jid });
if (folders.Count > 0)
{
var contact = new ZoomDirectoryContact { Name = c.ScreenName, ContactId = c.Jid };
if (folders.Count > 0)
{
contact.ParentFolderId = c.IsZoomRoom ? "rooms" : "contacts";
}
contacts.Add(contact);
contact.ParentFolderId = c.IsZoomRoom ? "rooms" : "contacts";
}
directory.AddContactsToDirectory(contacts);
contacts.Add(contact);
}
directory.AddContactsToDirectory(contacts);
}
catch (Exception e)
{
@@ -432,6 +433,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
private string _dispState;
private string _password;
private bool _isAirHostClientConnected;
private bool _isSharingBlackMagic;
private bool _isDirectPresentationConnected;
public string directPresentationPairingCode { get; set; }
/// <summary>
@@ -453,11 +458,51 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
}
public bool isAirHostClientConnected { get; set; }
public bool isAirHostClientConnected
{
get { return _isAirHostClientConnected; }
set
{
if (value != _isAirHostClientConnected)
{
_isAirHostClientConnected = value;
NotifyPropertyChanged("isAirHostClientConnected");
}
}
}
public bool isBlackMagicConnected { get; set; }
public bool isBlackMagicDataAvailable { get; set; }
public bool isDirectPresentationConnected { get; set; }
public bool isSharingBlackMagic { get; set; }
public bool isDirectPresentationConnected
{
get { return _isDirectPresentationConnected; }
set
{
if (value != _isDirectPresentationConnected)
{
_isDirectPresentationConnected = value;
NotifyPropertyChanged("isDirectPresentationConnected");
}
}
}
public bool isSharingBlackMagic
{
get { return _isSharingBlackMagic; }
set
{
if (value != _isSharingBlackMagic)
{
_isSharingBlackMagic = value;
NotifyPropertyChanged("isSharingBlackMagic");
}
}
}
/// <summary>
/// IOS Airplay code
/// </summary>
@@ -713,6 +758,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// </summary>
public class zEvent
{
public class StartLocalPresentMeeting
{
public bool Success { get; set; }
}
public class NeedWaitForHost
{
public bool Wait { get; set; }
@@ -780,7 +829,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private bool _paused;
private eSharingState _state;
public bool IsSharing;
public bool IsSharing { get; private set; }
[JsonProperty("paused")]
public bool Paused
@@ -920,6 +969,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
PhoneCallStatus_InCall,
PhoneCallStatus_Init,
}
public class MeetingNeedsPassword
{
[JsonProperty("needsPassword")]
public bool NeedsPassword { get; set; }
[JsonProperty("wrongAndRetry")]
public bool WrongAndRetry { get; set; }
}
}
/// <summary>
@@ -1161,11 +1219,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
set
{
if (value != _hideConfSelfVideo)
{
//if (value != _hideConfSelfVideo)
//{
_hideConfSelfVideo = value;
NotifyPropertyChanged("HideConfSelfVideo");
}
//}
}
}
@@ -1419,6 +1477,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public static List<Participant> GetGenericParticipantListFromParticipantsResult(
List<ListParticipant> participants)
{
if (participants.Count == 0)
{
return new List<Participant>();
}
//return participants.Select(p => new Participant
// {
// UserId = p.UserId,
@@ -1437,6 +1499,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
UserId = p.UserId,
Name = p.UserName,
IsHost = p.IsHost,
IsMyself = p.IsMyself,
CanMuteVideo = p.IsVideoCanMuteByHost,
CanUnmuteVideo = p.IsVideoCanUnmuteByHost,
AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED",

View File

@@ -63,6 +63,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
: base(key, name)
{
ParentCodec = codec;
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom;
}
/// <summary>

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
public string DefaultCallLayout { get; set; }
public int MinutesBeforeMeetingStart { get; set; }
}
}

View File

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