Compare commits

..

40 Commits

Author SHA1 Message Date
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
Andrew Welker
d64cbc639a Merge pull request #762 from PepperDash/release/1.9.2
Release/1.9.2
2021-07-28 18:47:34 -06:00
Andrew Welker
8404e7d5a4 Merge branch 'main' into release/1.9.2 2021-07-28 17:07:01 -06:00
Andrew Welker
e4135a958c Merge pull request #764 from PepperDash/hotfix/add-tsw7xx-types-to-factory
Hotfix/add tsw7xx types to factory
2021-07-28 17:06:45 -06:00
Andrew Welker
b026174cd2 Merge branch 'main' into release/1.9.2 2021-07-28 15:47:46 -06:00
47 changed files with 1855 additions and 1997 deletions

View File

@@ -8,12 +8,9 @@ on:
- bugfix/* - bugfix/*
- release/* - release/*
- development - development
pull_request:
branches:
- development
env: 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 name does not include extension. .sln is assumed
SOLUTION_PATH: PepperDashEssentials SOLUTION_PATH: PepperDashEssentials
SOLUTION_FILE: PepperDashEssentials SOLUTION_FILE: PepperDashEssentials

View File

@@ -450,13 +450,14 @@ namespace PepperDash.Essentials
return; return;
} }
uint fusionIpId = 0xf1;
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms) foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
{ {
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom; var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom;
if (room != null) if (room != null)
{ {
// default IPID
uint fusionIpId = 0xf1;
// default to no join map key // default to no join map key
string fusionJoinMapKey = string.Empty; string fusionJoinMapKey = string.Empty;
@@ -477,7 +478,7 @@ namespace PepperDash.Essentials
{ {
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey)); DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey));
@@ -489,7 +490,7 @@ namespace PepperDash.Essentials
{ {
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey)); DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
@@ -501,7 +502,7 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId); "Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey)); DeviceManager.AddDevice(new EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge"); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge");
@@ -514,26 +515,31 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
} }
fusionIpId += 1;
} }
else else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key);
}
} }
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded."); Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");
} }
private static void CreateMobileControlBridge(IEssentialsRoom room) private static void CreateMobileControlBridge(object room)
{ {
var mobileControl = GetMobileControlDevice(); var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return; 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..."); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control Bridge Added...");
} }

View File

@@ -150,7 +150,7 @@ namespace PepperDash.Essentials.Fusion
protected override void CreateSymbolAndBasicSigs(uint ipId) protected override void CreateSymbolAndBasicSigs(uint ipId)
{ {
Debug.Console(0, this, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId); Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid); FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use(); FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();

View File

@@ -149,8 +149,7 @@
<Compile Include="Room\Types\EssentialsNDisplayRoomBase.cs" /> <Compile Include="Room\Types\EssentialsNDisplayRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomConfig.cs" /> <Compile Include="Room\Config\EssentialsRoomConfig.cs" />
<Compile Include="Room\Types\EssentialsTechRoom.cs" /> <Compile Include="Room\Types\EssentialsTechRoom.cs" />
<Compile Include="Room\Types\Interfaces\IEssentialsHuddleSpaceRoom.cs" /> <Compile Include="Room\Types\IEssentialsHuddleSpaceRoom.cs" />
<Compile Include="Room\Types\Interfaces\IEssentialsHuddleVtc1Room.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" /> <Compile Include="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" /> <Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" /> <Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" />

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
using PepperDash.Core;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IHasDefaultDisplay
{
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; }
IBasicVolumeControls CurrentVolumeControls { get; }
event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
}
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange,
IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay
{
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
void RunRouteAction(string routeKey);
IHasScheduleAwareness ScheduleSource { get; }
string DefaultCodecRouteString { get; }
}
}

View File

@@ -1,24 +0,0 @@
using System;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay
{
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; }
IBasicVolumeControls CurrentVolumeControls { get; }
event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
}
}

View File

@@ -1,25 +0,0 @@
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange,
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback
{
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
void RunRouteAction(string routeKey);
IHasScheduleAwareness ScheduleSource { get; }
new BoolFeedback InCallFeedback { get; }
new BoolFeedback PrivacyModeIsOnFeedback { get; }
string DefaultCodecRouteString { get; }
}
}

View File

@@ -103,7 +103,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// 1202 /// 1202
/// </summary> /// </summary>
public const uint VCStagingInactivePopoverVisible = 1202; public const uint VCStagingInactivePopoverWithRecentsVisible = 1202;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@@ -121,6 +121,11 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public const uint VCRecentsVisible = 1206; public const uint VCRecentsVisible = 1206;
/// <summary>
/// 1202
/// </summary>
public const uint VCStagingInactivePopoverWithoutRecentsVisible = 1207;
/// <summary> /// <summary>
/// 1208 /// 1208
/// </summary> /// </summary>
@@ -243,6 +248,10 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public const uint VCCameraSelectBarWithoutModeVisible = 1261; public const uint VCCameraSelectBarWithoutModeVisible = 1261;
/// <summary>
/// 1262
/// </summary>
public const uint VCCameraAutoModeIsOnFb = 1262;
/// <summary> /// <summary>
/// 1271 /// 1271
@@ -743,10 +752,10 @@ namespace PepperDash.Essentials
/// 15044 Close button for source modal overlay /// 15044 Close button for source modal overlay
/// </summary> /// </summary>
public const uint SourceBackgroundOverlayClosePress = 15044; public const uint SourceBackgroundOverlayClosePress = 15044;
/// <summary> ///// <summary>
/// 15045 - Visibility for the bar containing call navigation button list ///// 15045 - Visibility for the bar containing call navigation button list
/// </summary> ///// </summary>
public const uint CallStagingBarVisible = 15045; //public const uint CallStagingBarVisible = 15045;
/// <summary> /// <summary>
/// 15046 /// 15046
/// </summary> /// </summary>
@@ -939,5 +948,24 @@ namespace PepperDash.Essentials
/// 15214 /// 15214
/// </summary> /// </summary>
public const uint PinDialogDot4 = 15214; 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

@@ -118,6 +118,14 @@ namespace PepperDash.Essentials
//----- through 3120 //----- through 3120
/// <summary>
/// 3201
/// </summary>
public const uint PasswordPromptMessageText = 3201;
/// <summary>
/// 3202
/// </summary>
public const uint PasswordPromptPasswordText = 3202;
/// <summary> /// <summary>
/// 3812 /// 3812

View File

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

View File

@@ -316,7 +316,7 @@ namespace PepperDash.Essentials.UIDrivers
void CommunicationMonitor_StatusChange(object sender, MonitorStatusChangeEventArgs e) void CommunicationMonitor_StatusChange(object sender, MonitorStatusChangeEventArgs e)
{ {
var c = sender as ICommunicationMonitor; var c = sender as ICommunicationMonitor;
if (StatusListDeviceIndexes.ContainsKey(c)) if (c != null && StatusListDeviceIndexes.ContainsKey(c))
{ {
var i = StatusListDeviceIndexes[c]; var i = StatusListDeviceIndexes[c];
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)e.Status; StatusList.UShortInputSig(i, 1).UShortValue = (ushort)e.Status;

View File

@@ -173,10 +173,28 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public PepperDash.Essentials.Core.Touchpanels.Keyboards.HabaneroKeyboardController Keyboard { get; private set; } public PepperDash.Essentials.Core.Touchpanels.Keyboards.HabaneroKeyboardController Keyboard { get; private set; }
private UiDisplayMode _currentMode;
/// <summary> /// <summary>
/// The mode showing. Presentation or call. /// The mode showing. Presentation or call.
/// </summary> /// </summary>
UiDisplayMode CurrentMode = UiDisplayMode.Start; UiDisplayMode CurrentMode
{
get
{
return _currentMode;
}
set
{
if (value != _currentMode)
{
_currentMode = value;
SetActivityFooterFeedbacks();
}
}
}
CTimer NextMeetingTimer; CTimer NextMeetingTimer;
@@ -207,6 +225,7 @@ namespace PepperDash.Essentials
MeetingOrContactMethodModalSrl = new SubpageReferenceList(TriList, UISmartObjectJoin.MeetingListSRL, 3, 3, 5); MeetingOrContactMethodModalSrl = new SubpageReferenceList(TriList, UISmartObjectJoin.MeetingListSRL, 3, 3, 5);
CurrentMode = UiDisplayMode.Start;
// buttons are added in SetCurrentRoom // buttons are added in SetCurrentRoom
//HeaderButtonsList = new SmartObjectHeaderButtonList(TriList.SmartObjects[UISmartObjectJoin.HeaderButtonList]); //HeaderButtonsList = new SmartObjectHeaderButtonList(TriList.SmartObjects[UISmartObjectJoin.HeaderButtonList]);
@@ -607,12 +626,25 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
void SetActivityFooterFeedbacks() void SetActivityFooterFeedbacks()
{ {
CallButtonSig.BoolValue = CurrentMode == UiDisplayMode.Call if (CurrentRoom != null)
{
var startMode = CurrentMode == UiDisplayMode.Start;
var presentationMode = CurrentMode == UiDisplayMode.Presentation;
var callMode = CurrentMode == UiDisplayMode.Call;
TriList.SetBool(StartPageVisibleJoin, startMode ? true : false);
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, presentationMode ? true : false);
if (!presentationMode)
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
CallButtonSig.BoolValue = callMode
&& CurrentRoom.ShutdownType == eShutdownType.None; && CurrentRoom.ShutdownType == eShutdownType.None;
ShareButtonSig.BoolValue = CurrentMode == UiDisplayMode.Presentation ShareButtonSig.BoolValue = presentationMode
&& CurrentRoom.ShutdownType == eShutdownType.None; && CurrentRoom.ShutdownType == eShutdownType.None;
EndMeetingButtonSig.BoolValue = CurrentRoom.ShutdownType != eShutdownType.None; EndMeetingButtonSig.BoolValue = CurrentRoom.ShutdownType != eShutdownType.None;
} }
}
/// <summary> /// <summary>
/// ///
@@ -623,14 +655,13 @@ namespace PepperDash.Essentials
return; return;
HideLogo(); HideLogo();
HideNextMeetingPopup(); HideNextMeetingPopup();
TriList.SetBool(StartPageVisibleJoin, false); //TriList.SetBool(StartPageVisibleJoin, false);
TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false); //TriList.SetBool(UIBoolJoin.SourceStagingBarVisible, false);
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false); //TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
if (CurrentSourcePageManager != null) if (CurrentSourcePageManager != null)
CurrentSourcePageManager.Hide(); CurrentSourcePageManager.Hide();
PowerOnFromCall(); PowerOnFromCall();
CurrentMode = UiDisplayMode.Call; CurrentMode = UiDisplayMode.Call;
SetActivityFooterFeedbacks();
VCDriver.Show(); VCDriver.Show();
} }
@@ -643,29 +674,25 @@ namespace PepperDash.Essentials
if (VCDriver.IsVisible) if (VCDriver.IsVisible)
VCDriver.Hide(); VCDriver.Hide();
HideNextMeetingPopup(); 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 // Run default source when room is off and share is pressed
if (!CurrentRoom.OnFeedback.BoolValue)
{
if (!CurrentRoom.OnFeedback.BoolValue) if (!CurrentRoom.OnFeedback.BoolValue)
{ {
// If there's no default, show UI elements // If there's no default, show UI elements
if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute()) if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute())
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
} }
}
else // room is on show what's active or select a source if nothing is yet active else // room is on show what's active or select a source if nothing is yet active
{ {
if(CurrentRoom.CurrentSourceInfo == null || CurrentRoom.CurrentSourceInfoKey == CurrentRoom.DefaultCodecRouteString) if(CurrentRoom.CurrentSourceInfo == null || (CurrentRoom.VideoCodec != null && CurrentRoom.CurrentSourceInfo.SourceDevice.Key == CurrentRoom.VideoCodec.OsdSource.Key))
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
else if (CurrentSourcePageManager != null) else if (CurrentSourcePageManager != null)
{
TriList.SetBool(UIBoolJoin.SelectASourceVisible, false);
CurrentSourcePageManager.Show(); CurrentSourcePageManager.Show();
} }
}
CurrentMode = UiDisplayMode.Presentation; CurrentMode = UiDisplayMode.Presentation;
SetupSourceList(); SetupSourceList();
SetActivityFooterFeedbacks();
} }
/// <summary> /// <summary>
@@ -707,6 +734,8 @@ namespace PepperDash.Essentials
if (CurrentRoom.CurrentSourceInfo == null) if (CurrentRoom.CurrentSourceInfo == null)
return; return;
CurrentMode = UiDisplayMode.Presentation;
if (CurrentRoom.CurrentSourceInfo.SourceDevice == null) if (CurrentRoom.CurrentSourceInfo.SourceDevice == null)
{ {
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
@@ -1105,6 +1134,30 @@ namespace PepperDash.Essentials
/// <param name="type"></param> /// <param name="type"></param>
void CurrentRoom_CurrentSingleSourceChange(SourceListItem info, ChangeType type) 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) if (_CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && _CurrentRoom.CurrentSourceInfo != null)
TriList.StringInput[UIStringJoin.CallSharedSourceNameText].StringValue = _CurrentRoom.CurrentSourceInfo.PreferredName; TriList.StringInput[UIStringJoin.CallSharedSourceNameText].StringValue = _CurrentRoom.CurrentSourceInfo.PreferredName;
} }
@@ -1202,12 +1255,12 @@ namespace PepperDash.Essentials
var value = _CurrentRoom.OnFeedback.BoolValue; var value = _CurrentRoom.OnFeedback.BoolValue;
TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value; TriList.BooleanInput[UIBoolJoin.RoomIsOn].BoolValue = value;
TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value; //TriList.BooleanInput[StartPageVisibleJoin].BoolValue = !value;
if (value) //ON if (value) //ON
{ {
SetupActivityFooterWhenRoomOn(); SetupActivityFooterWhenRoomOn();
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false; //TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = true; TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = true;
} }
@@ -1218,9 +1271,8 @@ namespace PepperDash.Essentials
VCDriver.Hide(); VCDriver.Hide();
SetupActivityFooterWhenRoomOff(); SetupActivityFooterWhenRoomOff();
ShowLogo(); ShowLogo();
SetActivityFooterFeedbacks(); //TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.VolumeDualMute1Visible].BoolValue = false; //TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
TriList.BooleanInput[UIBoolJoin.SourceStagingBarVisible].BoolValue = false;
// Clear this so that the pesky meeting warning can resurface every minute when off // Clear this so that the pesky meeting warning can resurface every minute when off
LastMeetingDismissedId = null; LastMeetingDismissedId = null;
} }

View File

@@ -83,6 +83,9 @@ namespace PepperDash.Essentials.UIDrivers.VC
StringBuilder SearchStringBuilder = new StringBuilder(); StringBuilder SearchStringBuilder = new StringBuilder();
BoolFeedback SearchStringBackspaceVisibleFeedback; BoolFeedback SearchStringBackspaceVisibleFeedback;
StringFeedback PasswordStringFeedback;
StringBuilder PasswordStringBuilder = new StringBuilder();
ModalDialog IncomingCallModal; ModalDialog IncomingCallModal;
eKeypadMode KeypadMode; eKeypadMode KeypadMode;
@@ -142,7 +145,10 @@ namespace PepperDash.Essentials.UIDrivers.VC
VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadVisible); VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadVisible);
StagingBarsInterlock = new JoinedSigInterlock(triList); 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 = new JoinedSigInterlock(triList);
StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress); StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingKeypadPress);
@@ -177,8 +183,22 @@ namespace PepperDash.Essentials.UIDrivers.VC
}); });
SearchStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.CodecDirectorySearchEntryText]); 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 "Tap for keyboard";
}
});
PasswordStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.PasswordPromptPasswordText]);
SetupDirectoryList();
SearchStringBackspaceVisibleFeedback = new BoolFeedback(() => SearchStringBuilder.Length > 0); SearchStringBackspaceVisibleFeedback = new BoolFeedback(() => SearchStringBuilder.Length > 0);
SearchStringBackspaceVisibleFeedback.LinkInputSig(triList.BooleanInput[UIBoolJoin.VCDirectoryBackspaceVisible]); SearchStringBackspaceVisibleFeedback.LinkInputSig(triList.BooleanInput[UIBoolJoin.VCDirectoryBackspaceVisible]);
@@ -196,6 +216,12 @@ namespace PepperDash.Essentials.UIDrivers.VC
triList.SetSigHeldAction(UIBoolJoin.VCDirectoryBackspacePress, 500, triList.SetSigHeldAction(UIBoolJoin.VCDirectoryBackspacePress, 500,
StartSearchBackspaceRepeat, StopSearchBackspaceRepeat, SearchKeypadBackspacePress); StartSearchBackspaceRepeat, StopSearchBackspaceRepeat, SearchKeypadBackspacePress);
if (Codec is IPasswordPrompt)
{
SetupPasswordPrompt();
}
} }
catch (Exception e) catch (Exception e)
{ {
@@ -354,7 +380,12 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (Codec.IsInCall) if (Codec.IsInCall)
stageJoin = UIBoolJoin.VCStagingActivePopoverVisible; stageJoin = UIBoolJoin.VCStagingActivePopoverVisible;
else else
stageJoin = UIBoolJoin.VCStagingInactivePopoverVisible; {
if (Codec is IHasCallHistory)
stageJoin = UIBoolJoin.VCStagingInactivePopoverWithRecentsVisible;
else
stageJoin = UIBoolJoin.VCStagingInactivePopoverWithoutRecentsVisible;
}
if (IsVisible) if (IsVisible)
StagingBarsInterlock.ShowInterlocked(stageJoin); StagingBarsInterlock.ShowInterlocked(stageJoin);
else else
@@ -513,13 +544,18 @@ namespace PepperDash.Essentials.UIDrivers.VC
var codecOffCameras = Codec as IHasCameraOff; var codecOffCameras = Codec as IHasCameraOff;
var supportsCameraOffMode = Codec.SupportsCameraOff;
var codecAutoCameras = Codec as IHasCameraAutoMode; var codecAutoCameras = Codec as IHasCameraAutoMode;
if (codecAutoCameras != null) var supportsAutoCameraMode = Codec.SupportsCameraAutoMode;
if (codecAutoCameras != null && supportsAutoCameraMode)
{ {
CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn()); CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn());
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true; TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true;
codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]); codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]);
codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(TriList.BooleanInput[UIBoolJoin.VCCameraAutoModeIsOnFb]);
//TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 1 Pressed"].SetSigFalseAction( //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 1 Pressed"].SetSigFalseAction(
//() => codecAutoCameras.CameraAutoModeOn()); //() => codecAutoCameras.CameraAutoModeOn());
@@ -554,7 +590,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
//TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 2 Pressed"].SetSigFalseAction( //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 2 Pressed"].SetSigFalseAction(
// () => ShowCameraManualMode()); // () => ShowCameraManualMode());
if (codecOffCameras != null) if (codecOffCameras != null && supportsCameraOffMode)
{ {
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true; TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true;
codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]); codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]);
@@ -769,12 +805,14 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (camerasCodec != null && camerasCodec.SelectedCamera != null) 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 dpad = CameraPtzPad;
var camera = camerasCodec.SelectedCamera as IHasCameraPtzControl; var camera = camerasCodec.SelectedCamera as IHasCameraPtzControl;
if (camera != null) if (camera != null)
{ {
Debug.Console(2, "Selected camera is IHasCameraPtzControl");
if (camerasCodec.SelectedCamera.CanTilt) if (camerasCodec.SelectedCamera.CanTilt)
{ {
dpad.SigUp.SetBoolSigAction((b) => dpad.SigUp.SetBoolSigAction((b) =>
@@ -839,25 +877,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 // Determines if codec is in manual camera control mode and shows feedback
void ShowCameraManualMode() void ShowCameraManualMode()
{ {
Debug.Console(2, "ShowCameraManualMode");
var inManualMode = true; var inManualMode = true;
var codecOffCameras = Codec as IHasCameraOff; var codecOffCameras = Codec as IHasCameraOff;
var codecAutoCameras = Codec as IHasCameraAutoMode; var codecAutoCameras = Codec as IHasCameraAutoMode;
var supportsAutoCameras = codecAutoCameras != null && Codec.SupportsCameraAutoMode;
if (codecOffCameras != null && codecOffCameras.CameraIsOffFeedback.BoolValue) if (codecOffCameras != null && codecOffCameras.CameraIsOffFeedback.BoolValue)
{ {
inManualMode = false; inManualMode = false;
var codecCameraMute = Codec as IHasCameraMute;
if (codecCameraMute != null)
{
codecCameraMute.CameraMuteOff();
inManualMode = true;
}
} }
// Clear auto mode // Clear auto mode
if (codecAutoCameras != null ) if (supportsAutoCameras)
{ {
if (codecAutoCameras.CameraAutoModeIsOnFeedback.BoolValue) if (codecAutoCameras.CameraAutoModeIsOnFeedback.BoolValue)
{ {
@@ -1005,21 +1064,20 @@ namespace PepperDash.Essentials.UIDrivers.VC
void SetupDirectoryList() void SetupDirectoryList()
{ {
var codec = Codec as IHasDirectory; var codec = Codec as IHasDirectory;
if (codec != null) if (codec == null)
{ {
return;
}
DirectoryList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCDirectoryList], DirectoryList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCDirectoryList],
true, 1300); true, 1300);
codec.DirectoryResultReturned += new EventHandler<DirectoryEventArgs>(dir_DirectoryResultReturned); codec.DirectoryResultReturned += dir_DirectoryResultReturned;
if (codec.PhonebookSyncState.InitialSyncComplete) if (codec.PhonebookSyncState.InitialSyncComplete)
SetCurrentDirectoryToRoot(); SetCurrentDirectoryToRoot();
else else
{ {
codec.PhonebookSyncState.InitialSyncCompleted += new EventHandler<EventArgs>(PhonebookSyncState_InitialSyncCompleted); codec.PhonebookSyncState.InitialSyncCompleted += PhonebookSyncState_InitialSyncCompleted;
}
RefreshDirectory();
} }
} }
@@ -1028,11 +1086,15 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// </summary> /// </summary>
void SetCurrentDirectoryToRoot() void SetCurrentDirectoryToRoot()
{ {
(Codec as IHasDirectory).SetCurrentDirectoryToRoot(); var hasDirectory = Codec as IHasDirectory;
if (hasDirectory == null)
{
return;
}
hasDirectory.SetCurrentDirectoryToRoot();
SearchKeypadClear(); SearchKeypadClear();
RefreshDirectory();
} }
/// <summary> /// <summary>
@@ -1044,10 +1106,17 @@ namespace PepperDash.Essentials.UIDrivers.VC
{ {
var codec = Codec as IHasDirectory; var codec = Codec as IHasDirectory;
if (codec == null)
{
return;
}
if (!codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue)
{
return;
}
SetCurrentDirectoryToRoot(); SetCurrentDirectoryToRoot();
RefreshDirectory();
} }
/// <summary> /// <summary>
@@ -1057,8 +1126,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// <param name="e"></param> /// <param name="e"></param>
void dir_DirectoryResultReturned(object sender, DirectoryEventArgs e) void dir_DirectoryResultReturned(object sender, DirectoryEventArgs e)
{ {
RefreshDirectory(e.Directory);
RefreshDirectory();
} }
/// <summary> /// <summary>
@@ -1090,13 +1158,24 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="dir"></param>
void RefreshDirectory() 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; ushort i = 0;
foreach (var r in (Codec as IHasDirectory).CurrentDirectoryResult.CurrentDirectoryResults) foreach (var r in directory.CurrentDirectoryResults)
{ {
if (i == DirectoryList.MaxCount) if (i == DirectoryList.MaxCount)
{ {
@@ -1116,21 +1195,35 @@ namespace PepperDash.Essentials.UIDrivers.VC
// If more than one contact method, show contact method modal dialog // If more than one contact method, show contact method modal dialog
DirectoryList.SetItemButtonAction(i, b => DirectoryList.SetItemButtonAction(i, b =>
{ {
if (!b) if (b)
{ {
return;
}
// Refresh the contact methods list // Refresh the contact methods list
RefreshContactMethodsModalList(dc); RefreshContactMethodsModalList(dc);
Parent.PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.MeetingsOrContacMethodsListVisible); 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 else
{ {
// If only one contact method, just dial that method // If only one contact method, just dial that method
DirectoryList.SetItemButtonAction(i, b => { if (!b) Codec.Dial(dc.ContactMethods[0].Number); }); DirectoryList.SetItemButtonAction(i, b => { if (!b) Codec.Dial(dc.ContactMethods[0].Number); });
} }
} }
else
{
Debug.Console(1, "Unable to dial contact. No availble ContactMethod(s) specified");
}
}
else // is DirectoryFolder else // is DirectoryFolder
{ {
DirectoryList.SetItemMainText(i, string.Format("[+] {0}", r.Name)); DirectoryList.SetItemMainText(i, string.Format("[+] {0}", r.Name));
@@ -1155,7 +1248,6 @@ namespace PepperDash.Essentials.UIDrivers.VC
DirectoryList.SetItemMainText(1, "No Results Found"); DirectoryList.SetItemMainText(1, "No Results Found");
} }
} }
void RefreshContactMethodsModalList(DirectoryContact contact) void RefreshContactMethodsModalList(DirectoryContact contact)
@@ -1201,7 +1293,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
var lc = Codec as IHasCodecLayouts; var lc = Codec as IHasCodecLayouts;
if (lc != null) if (lc != null)
{ {
TriList.SetSigFalseAction(UIBoolJoin.VCLayoutTogglePress, lc.LocalLayoutToggleSingleProminent);
lc.LocalLayoutFeedback.LinkInputSig(TriList.StringInput[UIStringJoin.VCLayoutModeText]); lc.LocalLayoutFeedback.LinkInputSig(TriList.StringInput[UIStringJoin.VCLayoutModeText]);
lc.LocalLayoutFeedback.OutputChange += (o,a) => lc.LocalLayoutFeedback.OutputChange += (o,a) =>
{ {
@@ -1214,6 +1306,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
var cisco = Codec as PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoSparkCodec; var cisco = Codec as PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoSparkCodec;
if (cisco != null) if (cisco != null)
{ {
TriList.SetSigFalseAction(UIBoolJoin.VCLayoutTogglePress, lc.LocalLayoutToggleSingleProminent);
// Cisco has min/max buttons that need special sauce // Cisco has min/max buttons that need special sauce
cisco.SharingContentIsOnFeedback.OutputChange += CiscoSharingAndPresentation_OutputChanges; cisco.SharingContentIsOnFeedback.OutputChange += CiscoSharingAndPresentation_OutputChanges;
//cisco.PresentationViewMaximizedFeedback.OutputChange += CiscoSharingAndPresentation_OutputChanges; //cisco.PresentationViewMaximizedFeedback.OutputChange += CiscoSharingAndPresentation_OutputChanges;
@@ -1221,7 +1314,16 @@ namespace PepperDash.Essentials.UIDrivers.VC
TriList.SetSigFalseAction(UIBoolJoin.VCMinMaxPress, cisco.MinMaxLayoutToggle); 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> /// <summary>
@@ -1249,7 +1351,21 @@ namespace PepperDash.Essentials.UIDrivers.VC
/// </summary> /// </summary>
void RevealKeyboard() 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; var kb = Parent.Keyboard;
kb.KeyPress -= Keyboard_DialKeyPress; kb.KeyPress -= Keyboard_DialKeyPress;
@@ -1271,6 +1387,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
SearchStringKeypadCheckEnables(); SearchStringKeypadCheckEnables();
kb.Show(); kb.Show();
} }
} }
/// <summary> /// <summary>
@@ -1326,6 +1443,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> /// <summary>
/// Call /// Call
/// </summary> /// </summary>
@@ -1339,6 +1482,11 @@ namespace PepperDash.Essentials.UIDrivers.VC
Parent.Keyboard.KeyPress -= Keyboard_SearchKeyPress; Parent.Keyboard.KeyPress -= Keyboard_SearchKeyPress;
} }
void DetachPasswordKeyboard()
{
Parent.Keyboard.KeyPress -= Keyboard_PasswordKeyPress;
}
/// <summary> /// <summary>
/// Shows the camera controls subpage /// Shows the camera controls subpage
/// </summary> /// </summary>
@@ -1592,6 +1740,40 @@ namespace PepperDash.Essentials.UIDrivers.VC
Parent.Keyboard.DisableGoButton(); Parent.Keyboard.DisableGoButton();
} }
/// <summary>
/// Clears the Password keypad
/// </summary>
void PasswordKeypadClear()
{
PasswordStringBuilder.Remove(0, SearchStringBuilder.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> /// <summary>
/// Returns the text value for the keypad dial entry field /// Returns the text value for the keypad dial entry field
@@ -1637,5 +1819,58 @@ namespace PepperDash.Essentials.UIDrivers.VC
Dial = 0, Dial = 0,
DTMF 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
PasswordStringBuilder.Remove(0, PasswordStringBuilder.Length);
_passwordPromptDialogVisible = true;
TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible);
RevealKeyboard();
}
void HidePasswordPrompt()
{
_passwordPromptDialogVisible = false;
Parent.Keyboard.Hide();
TriList.SetBool(UIBoolJoin.PasswordPromptDialogVisible, _passwordPromptDialogVisible);
}
} }
} }

View File

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

@@ -60,7 +60,6 @@ namespace PepperDash.Essentials.Core
DeviceCriticalSection.Enter(); DeviceCriticalSection.Enter();
AddDeviceEnabled = false; AddDeviceEnabled = false;
// PreActivate all devices // PreActivate all devices
Debug.Console(0,"****PreActivation starting...****");
foreach (var d in Devices.Values) foreach (var d in Devices.Values)
{ {
try try
@@ -70,12 +69,9 @@ namespace PepperDash.Essentials.Core
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(0, d, "ERROR: Device {1} PreActivation failure: {0}", e.Message, d.Key); Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e);
Debug.Console(1, d, "Stack Trace: {0}", e.StackTrace);
} }
} }
Debug.Console(0, "****PreActivation complete****");
Debug.Console(0, "****Activation starting...****");
// Activate all devices // Activate all devices
foreach (var d in Devices.Values) foreach (var d in Devices.Values)
@@ -87,14 +83,10 @@ namespace PepperDash.Essentials.Core
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(0, d, "ERROR: Device {1} Activation failure: {0}", e.Message, d.Key); Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e);
Debug.Console(1, d, "Stack Trace: {0}", e.StackTrace);
} }
} }
Debug.Console(0, "****Activation complete****");
Debug.Console(0, "****PostActivation starting...****");
// PostActivate all devices // PostActivate all devices
foreach (var d in Devices.Values) foreach (var d in Devices.Values)
{ {
@@ -105,13 +97,10 @@ namespace PepperDash.Essentials.Core
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(0, d, "ERROR: Device {1} PostActivation failure: {0}", e.Message, d.Key); Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e);
Debug.Console(1, d, "Stack Trace: {0}", e.StackTrace);
} }
} }
Debug.Console(0, "****PostActivation complete****");
OnAllDevicesActivated(); OnAllDevicesActivated();
} }
finally finally

View File

@@ -19,34 +19,13 @@ namespace PepperDash.Essentials.Core
protected EssentialsDevice(string key) protected EssentialsDevice(string key)
: base(key) : base(key)
{ {
SubscribeToActivateComplete();
} }
protected EssentialsDevice(string key, string name) protected EssentialsDevice(string key, string name)
: base(key, 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

@@ -156,6 +156,15 @@ namespace PepperDash.Essentials.Core
Debug.Console(0, Debug.ErrorLogLevel.Error, "Exception occurred while creating device {0}: {1}", dc.Key, ex.Message); Debug.Console(0, Debug.ErrorLogLevel.Error, "Exception occurred while creating device {0}: {1}", dc.Key, ex.Message);
Debug.Console(2, "{0}", ex.StackTrace); 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; return null;
} }
} }

View File

@@ -62,11 +62,6 @@ namespace PepperDash.Essentials.Core
ValueFunc = valueFunc; ValueFunc = valueFunc;
} }
public void SetValueFunc(Func<bool> newFunc)
{
ValueFunc = newFunc;
}
public override void FireUpdate() public override void FireUpdate()
{ {
bool newValue = InTestMode ? TestValue : ValueFunc.Invoke(); bool newValue = InTestMode ? TestValue : ValueFunc.Invoke();

View File

@@ -51,12 +51,6 @@ namespace PepperDash.Essentials.Core
ValueFunc = valueFunc; ValueFunc = valueFunc;
} }
public void SetValueFunc(Func<int> newFunc)
{
ValueFunc = newFunc;
}
public override void FireUpdate() public override void FireUpdate()
{ {
var newValue = InTestMode ? TestValue : ValueFunc.Invoke(); var newValue = InTestMode ? TestValue : ValueFunc.Invoke();

View File

@@ -52,10 +52,7 @@ namespace PepperDash.Essentials.Core
ValueFunc = valueFunc; ValueFunc = valueFunc;
} }
public void SetValueFunc(Func<string> newFunc)
{
ValueFunc = newFunc;
}
public override void FireUpdate() public override void FireUpdate()
{ {

View File

@@ -119,20 +119,8 @@ namespace PepperDash.Essentials.Core.Fusion
var slot = Global.ControlSystem.ProgramNumber; var slot = Global.ControlSystem.ProgramNumber;
var guidFilePath = Global.FilePathPrefix + var guidFilePath = Global.FilePathPrefix +
string.Format(@"{0}-FusionGuids-{1:X2}.json", InitialParametersClass.ProgramIDTag, _ipId);
var oldGuidFilePath = Global.FilePathPrefix +
string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag); string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag);
if (File.Exists(oldGuidFilePath))
{
Debug.Console(0, this, "Migrating from old Fusion GUID file to new Fusion GUID File");
File.Copy(oldGuidFilePath, guidFilePath);
File.Delete(oldGuidFilePath);
}
_guidFileExists = File.Exists(guidFilePath); _guidFileExists = File.Exists(guidFilePath);
// Check if file exists // Check if file exists
@@ -161,15 +149,7 @@ namespace PepperDash.Essentials.Core.Fusion
} }
AddPostActivationAction(() => PostActivate(guidFilePath)); AddPostActivationAction(() =>
}
catch (Exception e)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Building Fusion System Controller: {0}", e);
}
}
private void PostActivate(string guidFilePath)
{ {
CreateSymbolAndBasicSigs(_ipId); CreateSymbolAndBasicSigs(_ipId);
SetUpSources(); SetUpSources();
@@ -181,6 +161,12 @@ namespace PepperDash.Essentials.Core.Fusion
FusionRVI.GenerateFileForAllFusionDevices(); FusionRVI.GenerateFileForAllFusionDevices();
GenerateGuidFile(guidFilePath); GenerateGuidFile(guidFilePath);
});
}
catch (Exception e)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Building Fusion System Controller: {0}", e);
}
} }
protected string RoomGuid protected string RoomGuid
@@ -328,7 +314,7 @@ namespace PepperDash.Essentials.Core.Fusion
protected virtual void CreateSymbolAndBasicSigs(uint ipId) protected virtual void CreateSymbolAndBasicSigs(uint ipId)
{ {
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid); FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use(); FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();

View File

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

View File

@@ -1,149 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Represents an abstract controller device for a partition dividing rooms that are combinable
///
/// In Auto mode, it can use a partition sensor to automatically determine whether the partition is present.
///
/// In Manual mode it accepts user input to tell it whether the partition is present.
/// </summary>
public class EssentialsPartitionController : IPartitionController
{
private IPartitionStateProvider _partitionSensor;
private bool isInAutoMode;
private bool partitionPresent;
public EssentialsPartitionController(string key, string name, IPartitionStateProvider sensor, bool defaultToManualMode, List<string> adjacentRoomKeys)
{
Key = key;
Name = name;
AdjacentRoomKeys = adjacentRoomKeys;
if (sensor != null)
{
_partitionSensor = sensor;
if (!defaultToManualMode)
{
SetAutoMode();
}
else
{
SetManualMode();
}
}
else
{
SetManualMode();
}
PartitionPresentFeedback.FireUpdate();
}
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
if (isInAutoMode)
{
PartitionPresentFeedback.FireUpdate();
}
}
#region IPartitionController Members
public List<string> AdjacentRoomKeys { get; private set; }
public void SetAutoMode()
{
isInAutoMode = true;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => _partitionSensor.PartitionPresentFeedback.BoolValue);
}
else
{
PartitionPresentFeedback = new BoolFeedback(() => _partitionSensor.PartitionPresentFeedback.BoolValue);
}
if (_partitionSensor != null)
{
_partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
}
}
public void SetManualMode()
{
isInAutoMode = false;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => partitionPresent);
}
else
{
PartitionPresentFeedback = new BoolFeedback(() => partitionPresent);
}
if (_partitionSensor != null)
{
_partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange;
}
}
public void SetPartitionStatePresent()
{
if (!isInAutoMode)
{
partitionPresent = true;
PartitionPresentFeedback.FireUpdate();
}
}
public void SetPartitionStateNotPresent()
{
if (!isInAutoMode)
{
partitionPresent = false;
PartitionPresentFeedback.FireUpdate();
}
}
public void ToggglePartitionState()
{
if (!isInAutoMode)
{
partitionPresent = !partitionPresent;
PartitionPresentFeedback.FireUpdate();
}
}
#endregion
#region IPartitionStateProvider Members
public BoolFeedback PartitionPresentFeedback { get; private set; }
#endregion
#region IKeyName Members
public string Name { get; private set; }
#endregion
#region IKeyed Members
public string Key { get; private set; }
#endregion
}
}

View File

@@ -13,13 +13,13 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
[Description("Wrapper class for GLS Cresnet Partition Sensor")] [Description("Wrapper class for GLS Cresnet Partition Sensor")]
public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice, IPartitionStateProvider public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice
{ {
private GlsPartCn _partitionSensor; private GlsPartCn _partitionSensor;
public StringFeedback NameFeedback { get; private set; } public StringFeedback NameFeedback { get; private set; }
public BoolFeedback EnableFeedback { get; private set; } public BoolFeedback EnableFeedback { get; private set; }
public BoolFeedback PartitionPresentFeedback { get; private set; } public BoolFeedback PartitionSensedFeedback { get; private set; }
public BoolFeedback PartitionNotSensedFeedback { get; private set; } public BoolFeedback PartitionNotSensedFeedback { get; private set; }
public IntFeedback SensitivityFeedback { get; private set; } public IntFeedback SensitivityFeedback { get; private set; }
@@ -39,10 +39,10 @@ namespace PepperDash.Essentials.Core
RegisterCrestronGenericBase(_partitionSensor); RegisterCrestronGenericBase(_partitionSensor);
NameFeedback = new StringFeedback(() => Name); NameFeedback = new StringFeedback(() => Name);
EnableFeedback = new BoolFeedback(() => InTestMode ? TestEnableFeedback : _partitionSensor.EnableFeedback.BoolValue); EnableFeedback = new BoolFeedback(() => _partitionSensor.EnableFeedback.BoolValue);
PartitionPresentFeedback = new BoolFeedback(() => InTestMode ? TestPartitionSensedFeedback : _partitionSensor.PartitionSensedFeedback.BoolValue); PartitionSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionSensedFeedback.BoolValue);
PartitionNotSensedFeedback = new BoolFeedback(() => InTestMode ? !TestPartitionSensedFeedback : _partitionSensor.PartitionNotSensedFeedback.BoolValue); PartitionNotSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionNotSensedFeedback.BoolValue);
SensitivityFeedback = new IntFeedback(() => InTestMode ? TestSensitivityFeedback : _partitionSensor.SensitivityFeedback.UShortValue); SensitivityFeedback = new IntFeedback(() => _partitionSensor.SensitivityFeedback.UShortValue);
if (_partitionSensor != null) _partitionSensor.BaseEvent += PartitionSensor_BaseEvent; if (_partitionSensor != null) _partitionSensor.BaseEvent += PartitionSensor_BaseEvent;
}); });
@@ -61,7 +61,7 @@ namespace PepperDash.Essentials.Core
} }
case (GlsPartCn.PartitionSensedFeedbackEventId): case (GlsPartCn.PartitionSensedFeedbackEventId):
{ {
PartitionPresentFeedback.FireUpdate(); PartitionSensedFeedback.FireUpdate();
break; break;
} }
case (GlsPartCn.PartitionNotSensedFeedbackEventId): case (GlsPartCn.PartitionNotSensedFeedbackEventId):
@@ -93,9 +93,6 @@ namespace PepperDash.Essentials.Core
if (InTestMode) if (InTestMode)
{ {
TestEnableFeedback = state; TestEnableFeedback = state;
EnableFeedback.FireUpdate();
Debug.Console(1, this, "TestEnableFeedback: {0}", TestEnableFeedback.ToString()); Debug.Console(1, this, "TestEnableFeedback: {0}", TestEnableFeedback.ToString());
return; return;
} }
@@ -108,10 +105,6 @@ namespace PepperDash.Essentials.Core
if (InTestMode) if (InTestMode)
{ {
TestPartitionSensedFeedback = state; TestPartitionSensedFeedback = state;
PartitionPresentFeedback.FireUpdate();
PartitionNotSensedFeedback.FireUpdate();
Debug.Console(1, this, "TestPartitionSensedFeedback: {0}", TestPartitionSensedFeedback.ToString()); Debug.Console(1, this, "TestPartitionSensedFeedback: {0}", TestPartitionSensedFeedback.ToString());
return; return;
} }
@@ -124,8 +117,6 @@ namespace PepperDash.Essentials.Core
if (InTestMode) if (InTestMode)
{ {
TestSensitivityFeedback = value; TestSensitivityFeedback = value;
SensitivityFeedback.FireUpdate();
Debug.Console(1, this, "TestSensitivityFeedback: {0}", TestSensitivityFeedback); Debug.Console(1, this, "TestSensitivityFeedback: {0}", TestSensitivityFeedback);
return; return;
} }
@@ -195,7 +186,7 @@ namespace PepperDash.Essentials.Core
// link output to simpl // link output to simpl
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
EnableFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Enable.JoinNumber]); EnableFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Enable.JoinNumber]);
PartitionPresentFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]); PartitionSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]);
PartitionNotSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionNotSensed.JoinNumber]); PartitionNotSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionNotSensed.JoinNumber]);
SensitivityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Sensitivity.JoinNumber]); SensitivityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Sensitivity.JoinNumber]);
@@ -225,7 +216,7 @@ namespace PepperDash.Essentials.Core
IsOnline.FireUpdate(); IsOnline.FireUpdate();
NameFeedback.FireUpdate(); NameFeedback.FireUpdate();
EnableFeedback.FireUpdate(); EnableFeedback.FireUpdate();
PartitionPresentFeedback.FireUpdate(); PartitionSensedFeedback.FireUpdate();
PartitionNotSensedFeedback.FireUpdate(); PartitionNotSensedFeedback.FireUpdate();
SensitivityFeedback.FireUpdate(); SensitivityFeedback.FireUpdate();
} }
@@ -266,7 +257,7 @@ namespace PepperDash.Essentials.Core
public override EssentialsDevice BuildDevice(DeviceConfig dc) public override EssentialsDevice BuildDevice(DeviceConfig dc)
{ {
Debug.Console(1, "Factory Attempting to create new GlsPartitionSensorController Device"); Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device");
return new GlsPartitionSensorController(dc.Key, GetGlsPartCnDevice, dc); return new GlsPartitionSensorController(dc.Key, GetGlsPartCnDevice, dc);
} }

View File

@@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Describes the functionality of a device that senses and provides partition state
/// </summary>
public interface IPartitionStateProvider : IKeyName
{
BoolFeedback PartitionPresentFeedback { get; }
}
/// <summary>
/// Describes the functionality of a device that can provide partition state either manually via user input or optionally via a sensor state
/// </summary>
public interface IPartitionController : IPartitionStateProvider
{
List<string> AdjacentRoomKeys { get; }
void SetPartitionStatePresent();
void SetPartitionStateNotPresent();
void ToggglePartitionState();
void SetManualMode();
void SetAutoMode();
}
}

View File

@@ -203,6 +203,7 @@
<Compile Include="Devices\PC\Laptop.cs" /> <Compile Include="Devices\PC\Laptop.cs" />
<Compile Include="Devices\ReconfigurableDevice.cs" /> <Compile Include="Devices\ReconfigurableDevice.cs" />
<Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" /> <Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" />
<Compile Include="DeviceTypeInterfaces\IPasswordPrompt.cs" />
<Compile Include="DeviceTypeInterfaces\ITvPresetsProvider.cs" /> <Compile Include="DeviceTypeInterfaces\ITvPresetsProvider.cs" />
<Compile Include="DeviceTypeInterfaces\LanguageLabel.cs" /> <Compile Include="DeviceTypeInterfaces\LanguageLabel.cs" />
<Compile Include="DeviceTypeInterfaces\ILanguageProvider.cs" /> <Compile Include="DeviceTypeInterfaces\ILanguageProvider.cs" />
@@ -234,8 +235,6 @@
<Compile Include="Interfaces\ILogStringsWithLevel.cs" /> <Compile Include="Interfaces\ILogStringsWithLevel.cs" />
<Compile Include="Occupancy\GlsOccupancySensorPropertiesConfig.cs" /> <Compile Include="Occupancy\GlsOccupancySensorPropertiesConfig.cs" />
<Compile Include="Occupancy\GlsOirOccupancySensorController.cs" /> <Compile Include="Occupancy\GlsOirOccupancySensorController.cs" />
<Compile Include="PartitionSensor\EssentialsPartitionController.cs" />
<Compile Include="PartitionSensor\IPartitionStateProvider.cs" />
<Compile Include="Occupancy\OccupancyAggregatorConfig.cs" /> <Compile Include="Occupancy\OccupancyAggregatorConfig.cs" />
<Compile Include="Queues\ComsMessage.cs" /> <Compile Include="Queues\ComsMessage.cs" />
<Compile Include="Queues\ProcessStringMessage.cs" /> <Compile Include="Queues\ProcessStringMessage.cs" />
@@ -291,10 +290,6 @@
<Compile Include="Remotes\CrestronRemotePropertiesConfig.cs" /> <Compile Include="Remotes\CrestronRemotePropertiesConfig.cs" />
<Compile Include="Remotes\Hrxx0WirelessRemoteController.cs" /> <Compile Include="Remotes\Hrxx0WirelessRemoteController.cs" />
<Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" /> <Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" />
<Compile Include="Room\Combining\EssentialsRoomCombiner.cs" />
<Compile Include="Room\Combining\EssentialsRoomCombinerPropertiesConfig.cs" />
<Compile Include="Room\Combining\IEssentialsRoomCombiner.cs" />
<Compile Include="Room\Combining\RoomCombinationScenario.cs" />
<Compile Include="Room\EssentialsRoomBase.cs" /> <Compile Include="Room\EssentialsRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomScheduledEventsConfig.cs" /> <Compile Include="Room\Config\EssentialsRoomScheduledEventsConfig.cs" />
<Compile Include="Room\IEssentialsRoom.cs" /> <Compile Include="Room\IEssentialsRoom.cs" />

View File

@@ -1,264 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner
{
private EssentialsRoomCombinerPropertiesConfig _propertiesConfig;
private IRoomCombinationScenario _currentScenario;
private List<IEssentialsRoom> _rooms;
private bool isInAutoMode;
private CTimer _scenarioChangeDebounceTimer;
private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s
public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props)
: base(key)
{
_propertiesConfig = props;
Partitions = new List<IPartitionController>();
RoomCombinationScenarios = new List<IRoomCombinationScenario>();
if (_propertiesConfig.ScenarioChangeDebounceTimeSeconds > 0)
{
_scenarioChangeDebounceTimeSeconds = _propertiesConfig.ScenarioChangeDebounceTimeSeconds;
}
IsInAutoModeFeedback = new BoolFeedback(() => isInAutoMode);
// default to auto mode
isInAutoMode = true;
if (_propertiesConfig.defaultToManualMode)
{
isInAutoMode = false;
}
IsInAutoModeFeedback.FireUpdate();
CreateScenarios();
AddPostActivationAction(() =>
{
SetupPartitionStateProviders();
SetRooms();
});
}
void CreateScenarios()
{
RoomCombinationScenarios = new List<IRoomCombinationScenario>();
foreach (var scenarioConfig in _propertiesConfig.Scenarios)
{
var scenario = new RoomCombinationScenario(scenarioConfig);
RoomCombinationScenarios.Add(scenario);
}
}
void SetRooms()
{
_rooms = new List<IEssentialsRoom>();
foreach (var roomKey in _propertiesConfig.RoomKeys)
{
var room = DeviceManager.GetDeviceForKey(roomKey) as IEssentialsRoom;
if (room != null)
{
_rooms.Add(room);
}
}
}
void SetupPartitionStateProviders()
{
foreach (var pConfig in _propertiesConfig.Partitions)
{
var sensor = DeviceManager.GetDeviceForKey(pConfig.DeviceKey) as IPartitionStateProvider;
var partition = new EssentialsPartitionController(pConfig.Key, pConfig.Name, sensor, _propertiesConfig.defaultToManualMode, pConfig.AdjacentRoomKeys);
partition.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
Partitions.Add(partition);
}
}
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
StartDebounceTimer();
}
void StartDebounceTimer()
{
var time = _scenarioChangeDebounceTimeSeconds * 1000;
if (_scenarioChangeDebounceTimer == null)
{
_scenarioChangeDebounceTimer = new CTimer((o) => DetermineRoomCombinationScenario(), time);
}
else
{
_scenarioChangeDebounceTimer.Reset(time);
}
}
/// <summary>
/// Determines the current room combination scenario based on the state of the partition sensors
/// </summary>
void DetermineRoomCombinationScenario()
{
if (_scenarioChangeDebounceTimer != null)
{
_scenarioChangeDebounceTimer.Dispose();
_scenarioChangeDebounceTimer = null;
}
var currentScenario = RoomCombinationScenarios.FirstOrDefault((s) =>
{
// iterate the partition states
foreach (var partitionState in s.PartitionStates)
{
// get the partition by key
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
if (partition != null && partitionState.PartitionPresent != partition.PartitionPresentFeedback.BoolValue)
{
// the partition can't be found or the state doesn't match
return false;
}
}
// if it hasn't returned false by now we have the matching scenario
return true;
});
if (currentScenario != null)
{
CurrentScenario = currentScenario;
}
}
#region IEssentialsRoomCombiner Members
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
public IRoomCombinationScenario CurrentScenario
{
get
{
return _currentScenario;
}
set
{
if (value != _currentScenario)
{
_currentScenario = value;
Debug.Console(1, this, "Current Scenario: {0}", _currentScenario.Name);
var handler = RoomCombinationScenarioChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
}
public BoolFeedback IsInAutoModeFeedback { get; private set; }
public void SetAutoMode()
{
isInAutoMode = true;
IsInAutoModeFeedback.FireUpdate();
}
public void SetManualMode()
{
isInAutoMode = false;
IsInAutoModeFeedback.FireUpdate();
}
public void ToggleMode()
{
isInAutoMode = !isInAutoMode;
IsInAutoModeFeedback.FireUpdate();
}
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; private set; }
public List<IPartitionController> Partitions { get; private set; }
public void TogglePartitionState(string partitionKey)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)) as IPartitionController;
if (partition != null)
{
partition.ToggglePartitionState();
}
}
public void SetRoomCombinationScenario(string scenarioKey)
{
if (isInAutoMode)
{
Debug.Console(0, this, "Cannot set room combination scenario when in auto mode. Set to auto mode first.");
return;
}
// Get the scenario
var scenario = RoomCombinationScenarios.FirstOrDefault((s) => s.Key.Equals(scenarioKey));
// Set the parition states from the scenario manually
if (scenario != null)
{
foreach (var partitionState in scenario.PartitionStates)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
if (partition != null)
{
if (partitionState.PartitionPresent)
{
partition.SetPartitionStatePresent();
}
else
{
partition.SetPartitionStateNotPresent();
}
}
}
}
}
#endregion
}
public class EssentialsRoomCombinerFactory : EssentialsDeviceFactory<EssentialsRoomCombiner>
{
public EssentialsRoomCombinerFactory()
{
TypeNames = new List<string> { "essentialsroomcombiner" };
}
public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new EssentialsRoomCombiner Device");
var props = dc.Properties.ToObject<EssentialsRoomCombinerPropertiesConfig>();
return new EssentialsRoomCombiner(dc.Key, props);
}
}
}

View File

@@ -1,111 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Config properties for an EssentialsRoomCombiner device
/// </summary>
public class EssentialsRoomCombinerPropertiesConfig
{
/// <summary>
/// The list of partitions that device the rooms
/// </summary>
[JsonProperty("partitions")]
public List<PartitionConfig> Partitions {get; set;}
/// <summary>
/// The list of combinations scenarios for the rooms
/// </summary>
[JsonProperty("scenarios")]
public List<RoomCombinationScenarioConfig> Scenarios { get; set; }
/// <summary>
/// The list of rooms keys that can be combined
/// </summary>
[JsonProperty("roomMap")]
public List<string> RoomKeys {get; set;}
/// <summary>
/// Set to true to default to manual mode
/// </summary>
[JsonProperty("defaultToManualMode")]
public bool defaultToManualMode { get; set; }
/// <summary>
/// The key of the scenario to default to at system startup if in manual mode
/// </summary>
[JsonProperty("defaultScenarioKey")]
public string defaultScenarioKey { get; set; }
[JsonProperty("scenarioChangeDebounceTimeSeconds")]
public int ScenarioChangeDebounceTimeSeconds { get; set; }
}
/// <summary>
/// Config properties for a partition that separates rooms
/// </summary>
public class PartitionConfig : IKeyName
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// Key of the device that implements IPartitionStateProvider to provide the state of the partition
/// </summary>
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
/// <summary>
/// Keys of the rooms that this partion would be located between
/// </summary>
[JsonProperty("adjacentRoomKeys")]
public List<string> AdjacentRoomKeys { get; set; }
}
/// <summary>
/// Config propeties for a room combination scenario
/// </summary>
public class RoomCombinationScenarioConfig : IKeyName
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("partitionStates")]
public List<PartitionState> PartitionStates { get; set; }
[JsonProperty("uiMap")]
public Dictionary<string, string> UiMap { get; set; }
[JsonProperty("activationActions")]
public List<DeviceActionWrapper> ActivationActions { get; set; }
[JsonProperty("deactivationActions")]
public List<DeviceActionWrapper> DeactivationActions { get; set; }
}
/// <summary>
/// Config properties to represent the state of a partition sensor in a RoomCombinationScenario
/// </summary>
public class PartitionState
{
[JsonProperty("partitionKey")]
public string PartitionKey { get; set; }
[JsonProperty("partitionSensedState")]
public bool PartitionPresent { get; set; }
}
}

View File

@@ -1,92 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Describes the functionality for an EssentailsRoomCombiner device
/// </summary>
public interface IEssentialsRoomCombiner : IKeyed
{
/// <summary>
/// Indicates that the room combination scenario has changed
/// </summary>
event EventHandler<EventArgs> RoomCombinationScenarioChanged;
/// <summary>
/// The current room combination scenario
/// </summary>
IRoomCombinationScenario CurrentScenario { get; }
/// <summary>
/// When true, indicates the current mode is auto mode
/// </summary>
BoolFeedback IsInAutoModeFeedback {get;}
/// <summary>
/// Sets auto mode
/// </summary>
void SetAutoMode();
/// <summary>
/// Sets manual mode
/// </summary>
void SetManualMode();
/// <summary>
/// Toggles the current mode between auto and manual
/// </summary>
void ToggleMode();
/// <summary>
/// The available room combinatino scenarios
/// </summary>
List<IRoomCombinationScenario> RoomCombinationScenarios { get; }
/// <summary>
/// The partition
/// </summary>
List<IPartitionController> Partitions { get; }
/// <summary>
/// Toggles the state of a manual partition sensor
/// </summary>
/// <param name="partitionKey"></param>
void TogglePartitionState(string partitionKey);
/// <summary>
/// Sets the room combination scenario (if in manual mode)
/// </summary>
/// <param name="scenarioKey"></param>
void SetRoomCombinationScenario(string scenarioKey);
}
public interface IRoomCombinationScenario : IKeyName
{
/// <summary>
/// When true, indicates that this room combination scenario is active
/// </summary>
BoolFeedback IsActiveFeedback { get; }
/// <summary>
/// Activates this room combination scenario
/// </summary>
void Activate();
/// <summary>
/// The state of the partitions that would activate this scenario
/// </summary>
List<PartitionState> PartitionStates { get; }
/// <summary>
/// The mapping of UIs by key to rooms by key
/// </summary>
Dictionary<string, string> UiMap { get; set; }
}
}

View File

@@ -1,83 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Represents a room combination scenario
/// </summary>
public class RoomCombinationScenario: IRoomCombinationScenario
{
private RoomCombinationScenarioConfig _config;
public string Key { get; set; }
public string Name { get; set; }
public List<PartitionState> PartitionStates { get; private set; }
public Dictionary<string, string> UiMap { get; set; }
private bool _isActive;
public BoolFeedback IsActiveFeedback { get; private set; }
List<DeviceActionWrapper> activationActions;
List<DeviceActionWrapper> deactivationActions;
public RoomCombinationScenario(RoomCombinationScenarioConfig config)
{
Key = config.Key;
Name = config.Name;
PartitionStates = config.PartitionStates;
UiMap = config.UiMap;
activationActions = config.ActivationActions;
deactivationActions = config.DeactivationActions;
_config = config;
IsActiveFeedback = new BoolFeedback(() => _isActive);
}
public void Activate()
{
if (activationActions != null)
{
foreach (var action in activationActions)
{
DeviceJsonApi.DoDeviceAction(action);
}
}
_isActive = true;
IsActiveFeedback.FireUpdate();
}
public void Deactivate()
{
if (deactivationActions != null)
{
foreach (var action in deactivationActions)
{
DeviceJsonApi.DoDeviceAction(action);
}
}
_isActive = false;
IsActiveFeedback.FireUpdate();
}
}
}

View File

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

View File

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

View File

@@ -69,6 +69,22 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("directoryResults")] [JsonProperty("directoryResults")]
public List<DirectoryItem> CurrentDirectoryResults { get; private set; } 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> /// <summary>
/// Used to store the ID of the current folder for CurrentDirectoryResults /// Used to store the ID of the current folder for CurrentDirectoryResults
/// </summary> /// </summary>
@@ -104,6 +120,15 @@ namespace PepperDash.Essentials.Devices.Common.Codec
SortDirectory(); 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> /// <summary>
/// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically /// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically
/// </summary> /// </summary>

View File

@@ -314,7 +314,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
FarEndIsSharingContentFeedback = new BoolFeedback(FarEndIsSharingContentFeedbackFunc); FarEndIsSharingContentFeedback = new BoolFeedback(FarEndIsSharingContentFeedbackFunc);
CameraIsOffFeedback = new BoolFeedback(() => CodecStatus.Status.Video.Input.MainVideoMute.BoolValue); CameraIsOffFeedback = new BoolFeedback(() => CodecStatus.Status.Video.Input.MainVideoMute.BoolValue);
CameraIsMutedFeedback = CameraIsOffFeedback; CameraIsMutedFeedback = CameraIsOffFeedback;
SupportsCameraOff = true;
PresentationViewMaximizedFeedback = new BoolFeedback(() => CurrentPresentationView == "Maximized"); 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.PeoplePresence.ValueChangedAction = RoomIsOccupiedFeedback.FireUpdate;
CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate; CodecStatus.Status.RoomAnalytics.PeopleCount.Current.ValueChangedAction = PeopleCountFeedback.FireUpdate;
CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = CameraAutoModeIsOnFeedback.FireUpdate; CodecStatus.Status.Cameras.SpeakerTrack.Status.ValueChangedAction = CameraAutoModeIsOnFeedback.FireUpdate;
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.Mode.ValueChangedAction = SelfviewIsOnFeedback.FireUpdate;
CodecStatus.Status.Video.Selfview.PIPPosition.ValueChangedAction = ComputeSelfviewPipStatus; CodecStatus.Status.Video.Selfview.PIPPosition.ValueChangedAction = ComputeSelfviewPipStatus;
CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout; CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout;
@@ -550,13 +551,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CrestronConsole.AddNewConsoleCommand(GetPhonebook, "GetCodecPhonebook", "Triggers a refresh of the codec phonebook", ConsoleAccessLevelEnum.AccessOperator); 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); 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; var socket = Communication as ISocketStatus;
if (socket != null) if (socket != null)
{ {
@@ -567,7 +561,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CommunicationMonitor.Start(); CommunicationMonitor.Start();
const string prefix = "xFeedback register "; string prefix = "xFeedback register ";
CliFeedbackRegistrationExpression = CliFeedbackRegistrationExpression =
prefix + "/Configuration" + Delimiter + prefix + "/Configuration" + Delimiter +
@@ -586,9 +580,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
prefix + "/Event/Bookings" + Delimiter + prefix + "/Event/Bookings" + Delimiter +
prefix + "/Event/CameraPresetListUpdated" + Delimiter + prefix + "/Event/CameraPresetListUpdated" + Delimiter +
prefix + "/Event/UserInterface/Presentation/ExternalSource/Selected/SourceIdentifier" + Delimiter; prefix + "/Event/UserInterface/Presentation/ExternalSource/Selected/SourceIdentifier" + Delimiter;
}
#endregion return base.CustomActivate();
}
/// <summary> /// <summary>
/// Fires when initial codec sync is completed. Used to then send commands to get call history, phonebook, bookings, etc. /// Fires when initial codec sync is completed. Used to then send commands to get call history, phonebook, bookings, etc.

View File

@@ -277,9 +277,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public SoftwareID SoftwareID { get; set; } 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 public class Status2 : ValueProperty
@@ -311,6 +327,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public SpeakerTrack() public SpeakerTrack()
{ {
Status = new Status2(); Status = new Status2();
Availability = new Availability();
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
@@ -49,7 +50,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{ {
private List<Participant> _currentParticipants; private List<Participant> _currentParticipants;
public List<Participant> CurrentParticipants { public List<Participant> CurrentParticipants
{
get { return _currentParticipants; } get { return _currentParticipants; }
set set
{ {

View File

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

View File

@@ -65,8 +65,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public bool ShowSelfViewByDefault { get; protected set; } public bool ShowSelfViewByDefault { get; protected set; }
protected bool SupportsCameraOff; public bool SupportsCameraOff { get; protected set; }
protected bool SupportsCameraAutoMode; public bool SupportsCameraAutoMode { get; protected set; }
public bool IsReady { get; protected set; } public bool IsReady { get; protected set; }

View File

@@ -276,6 +276,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (zoomRooms.Count > 0) if (zoomRooms.Count > 0)
{ {
// If so, setup a rooms and contacts folder and add them. // If so, setup a rooms and contacts folder and add them.
directory.ResultsFolderId = "root";
roomFolder.Name = "Rooms"; roomFolder.Name = "Rooms";
roomFolder.ParentFolderId = "root"; roomFolder.ParentFolderId = "root";
roomFolder.FolderId = "rooms"; roomFolder.FolderId = "rooms";
@@ -292,12 +295,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
try 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 ZoomDirectoryContact { Name = c.ScreenName, ContactId = c.Jid }; var contact = new ZoomDirectoryContact { 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) if (folders.Count > 0)
{ {
contact.ParentFolderId = c.IsZoomRoom ? "rooms" : "contacts"; contact.ParentFolderId = c.IsZoomRoom ? "rooms" : "contacts";
@@ -308,7 +316,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
directory.AddContactsToDirectory(contacts); directory.AddContactsToDirectory(contacts);
} }
}
catch (Exception e) catch (Exception e)
{ {
Debug.Console(1, "Error converting Zoom Phonebook results to generic: {0}", e); Debug.Console(1, "Error converting Zoom Phonebook results to generic: {0}", e);
@@ -920,6 +927,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
PhoneCallStatus_InCall, PhoneCallStatus_InCall,
PhoneCallStatus_Init, PhoneCallStatus_Init,
} }
public class MeetingNeedsPassword
{
[JsonProperty("needsPassword")]
public bool NeedsPassword { get; set; }
[JsonProperty("wrongAndRetry")]
public bool WrongAndRetry { get; set; }
}
} }
/// <summary> /// <summary>
@@ -1161,11 +1177,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
set set
{ {
if (value != _hideConfSelfVideo) //if (value != _hideConfSelfVideo)
{ //{
_hideConfSelfVideo = value; _hideConfSelfVideo = value;
NotifyPropertyChanged("HideConfSelfVideo"); NotifyPropertyChanged("HideConfSelfVideo");
} //}
} }
} }

View File

@@ -3,18 +3,17 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharpPro.CrestronThread; using Crestron.SimplSharpPro.CrestronThread;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Core.Intersystem.Tokens;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Core.Routing;
using PepperDash.Essentials.Core.Queues;
using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco;
@@ -25,15 +24,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor,
IRouting, IRouting,
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasParticipantAudioMute, IHasSelfviewSize IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt
{ {
private const long MeetingRefreshTimer = 60000; private const long MeetingRefreshTimer = 60000;
private const uint DefaultMeetingDurationMin = 30; private const uint DefaultMeetingDurationMin = 30;
private const string Delimiter = "\x0D\x0A"; private const string Delimiter = "\x0D\x0A";
private readonly CrestronQueue<string> _receiveQueue;
private readonly GenericQueue _receiveQueue;
//private readonly CrestronQueue<string> _receiveQueue;
private readonly Thread _receiveThread; //private readonly Thread _receiveThread;
private readonly ZoomRoomSyncState _syncState; private readonly ZoomRoomSyncState _syncState;
public bool CommDebuggingIsOn; public bool CommDebuggingIsOn;
@@ -43,6 +45,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private StringBuilder _jsonMessage; private StringBuilder _jsonMessage;
private int _previousVolumeLevel; private int _previousVolumeLevel;
private CameraBase _selectedCamera; private CameraBase _selectedCamera;
private string _lastDialedMeetingNumber;
private readonly ZoomRoomPropertiesConfig _props; private readonly ZoomRoomPropertiesConfig _props;
@@ -51,11 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
_props = JsonConvert.DeserializeObject<ZoomRoomPropertiesConfig>(config.Properties.ToString()); _props = JsonConvert.DeserializeObject<ZoomRoomPropertiesConfig>(config.Properties.ToString());
// The queue that will collect the repsonses in the order they are received _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512);
_receiveQueue = new CrestronQueue<string>(1024);
// The thread responsible for dequeuing and processing the messages
_receiveThread = new Thread(o => ProcessQueue(), null) { Priority = Thread.eThreadPriority.MediumPriority };
Communication = comm; Communication = comm;
@@ -95,6 +94,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this); eRoutingPortConnectionType.Hdmi, null, this);
Output2 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut,
eRoutingSignalType.Video,
eRoutingPortConnectionType.DisplayPort, null, this);
SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc);
CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc);
@@ -120,7 +123,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Participants = new CodecParticipants(); Participants = new CodecParticipants();
SupportsCameraOff = _props.SupportsCameraOff; SupportsCameraOff = true; // Always allow turning off the camera for zoom calls?
SupportsCameraAutoMode = _props.SupportsCameraAutoMode; SupportsCameraAutoMode = _props.SupportsCameraAutoMode;
PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc); PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc);
@@ -135,7 +138,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc); ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc);
NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc); NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc);
} }
public CommunicationGather PortGather { get; private set; } public CommunicationGather PortGather { get; private set; }
@@ -154,7 +156,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
get get
{ {
return () => CrestronEnvironment.ScaleWithLimits(Configuration.Audio.Output.Volume, 100, 0, 65535, 0); return () =>
{
var scaledVol = CrestronEnvironment.ScaleWithLimits(Configuration.Audio.Output.Volume, 100, 0, 65535, 0);
if (Configuration.Audio.Output.Volume != 0)
{
Debug.Console(2, this, "Storing previous volume level as: {0}, scaled: {1}", Configuration.Audio.Output.Volume,
scaledVol);
_previousVolumeLevel = scaledVol; // Store the previous level for recall
}
return scaledVol;
};
} }
} }
@@ -252,6 +266,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public RoutingInputPort CodecOsdIn { get; private set; } public RoutingInputPort CodecOsdIn { get; private set; }
public RoutingOutputPort Output1 { get; private set; } public RoutingOutputPort Output1 { get; private set; }
public RoutingOutputPort Output2 { get; private set; }
#region ICommunicationMonitor Members #region ICommunicationMonitor Members
@@ -277,7 +292,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var handler = CameraSelected; var handler = CameraSelected;
if (handler != null) if (handler != null)
{ {
handler(this, new CameraSelectedEventArgs(SelectedCamera)); handler(this, new CameraSelectedEventArgs(_selectedCamera));
} }
} }
} }
@@ -314,6 +329,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public BoolFeedback SelfviewIsOnFeedback { get; private set; } public BoolFeedback SelfviewIsOnFeedback { get; private set; }
public void GetSelfViewMode()
{
SendText("zConfiguration Video hide_conf_self_video");
}
public void SelfViewModeOn() public void SelfViewModeOn()
{ {
SendText("zConfiguration Video hide_conf_self_video: off"); SendText("zConfiguration Video hide_conf_self_video: off");
@@ -346,6 +366,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public CodecDirectory CurrentDirectoryResult public CodecDirectory CurrentDirectoryResult
{ {
get { return _currentDirectoryResult; } get { return _currentDirectoryResult; }
private set
{
_currentDirectoryResult = value;
Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0}",
_currentDirectoryResult.ResultsFolderId);
CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate();
OnDirectoryResultReturned(_currentDirectoryResult);
}
} }
public CodecPhonebookSyncState PhonebookSyncState { get; private set; } public CodecPhonebookSyncState PhonebookSyncState { get; private set; }
@@ -359,9 +390,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
c => c.Name.IndexOf(searchString, 0, StringComparison.OrdinalIgnoreCase) > -1)); c => c.Name.IndexOf(searchString, 0, StringComparison.OrdinalIgnoreCase) > -1));
DirectoryBrowseHistoryStack.Clear(); DirectoryBrowseHistoryStack.Clear();
_currentDirectoryResult = directoryResults; CurrentDirectoryResult = directoryResults;
OnDirectoryResultReturned(directoryResults);
} }
public void GetDirectoryFolderContents(string folderId) public void GetDirectoryFolderContents(string folderId)
@@ -373,18 +402,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
DirectoryBrowseHistoryStack.Push(_currentDirectoryResult); DirectoryBrowseHistoryStack.Push(_currentDirectoryResult);
_currentDirectoryResult = directoryResults; CurrentDirectoryResult = directoryResults;
OnDirectoryResultReturned(directoryResults);
} }
public void SetCurrentDirectoryToRoot() public void SetCurrentDirectoryToRoot()
{ {
DirectoryBrowseHistoryStack.Clear(); DirectoryBrowseHistoryStack.Clear();
_currentDirectoryResult = DirectoryRoot; CurrentDirectoryResult = DirectoryRoot;
OnDirectoryResultReturned(DirectoryRoot);
} }
public void GetDirectoryParentFolderContents() public void GetDirectoryParentFolderContents()
@@ -396,9 +421,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var currentDirectory = DirectoryBrowseHistoryStack.Pop(); var currentDirectory = DirectoryBrowseHistoryStack.Pop();
_currentDirectoryResult = currentDirectory; CurrentDirectoryResult = currentDirectory;
OnDirectoryResultReturned(currentDirectory);
} }
public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; } public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; }
@@ -536,7 +559,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
break; break;
} }
} }
}; };
@@ -563,7 +585,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
LocalLayoutFeedback.FireUpdate(); LocalLayoutFeedback.FireUpdate();
break; break;
} }
} }
}; };
@@ -665,16 +686,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void SetUpDirectory() private void SetUpDirectory()
{ {
DirectoryRoot = new CodecDirectory(); DirectoryRoot = new CodecDirectory() {ResultsFolderId = "root"};
_currentDirectoryResult = DirectoryRoot; CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => CurrentDirectoryResult.ResultsFolderId != "root");
CurrentDirectoryResult = DirectoryRoot;
DirectoryBrowseHistory = new List<CodecDirectory>(); DirectoryBrowseHistory = new List<CodecDirectory>();
DirectoryBrowseHistoryStack = new Stack<CodecDirectory>(); DirectoryBrowseHistoryStack = new Stack<CodecDirectory>();
CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => _currentDirectoryResult != DirectoryRoot);
CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate();
} }
private void SetUpRouting() private void SetUpRouting()
@@ -685,6 +704,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// Set up output ports // Set up output ports
OutputPorts.Add(Output1); OutputPorts.Add(Output1);
OutputPorts.Add(Output2);
} }
/// <summary> /// <summary>
@@ -719,15 +739,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
CrestronConsole.AddNewConsoleCommand(s => GetBookings(), "GetZoomRoomBookings", CrestronConsole.AddNewConsoleCommand(s => GetBookings(), "GetZoomRoomBookings",
"Triggers a refresh of the booking data for today", ConsoleAccessLevelEnum.AccessOperator); "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; var socket = Communication as ISocketStatus;
if (socket != null) if (socket != null)
{ {
@@ -739,21 +750,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Communication.Connect(); Communication.Connect();
CommunicationMonitor.Start(); CommunicationMonitor.Start();
}
#endregion return base.CustomActivate();
}
public void SetCommDebug(string s) public void SetCommDebug(string s)
{ {
if (s == "1") if (s == "1")
{ {
CommDebuggingIsOn = true; CommDebuggingIsOn = true;
Debug.Console(0, this, "Comm Debug Enabled."); Debug.Console(1, this, "Comm Debug Enabled.");
} }
else else
{ {
CommDebuggingIsOn = false; CommDebuggingIsOn = false;
Debug.Console(0, this, "Comm Debug Disabled."); Debug.Console(1, this, "Comm Debug Disabled.");
} }
} }
@@ -790,37 +801,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
//if (CommDebuggingIsOn) //if (CommDebuggingIsOn)
// Debug.Console(1, this, "Gathered: '{0}'", args.Text); // Debug.Console(1, this, "Gathered: '{0}'", args.Text);
_receiveQueue.Enqueue(args.Text); _receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage));
// If the receive thread has for some reason stopped, this will restart it
if (_receiveThread.ThreadState != Thread.eThreadStates.ThreadRunning)
{
_receiveThread.Start();
}
}
/// <summary>
/// Runs in it's own thread to dequeue messages in the order they were received to be processed
/// </summary>
/// <returns></returns>
private object ProcessQueue()
{
try
{
while (true)
{
var message = _receiveQueue.Dequeue();
ProcessMessage(message);
}
}
catch (Exception e)
{
Debug.Console(1, this, "Error Processing Queue: {0}", e);
}
return null;
} }
@@ -891,7 +872,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// Counts the curly braces // Counts the curly braces
if (message.Contains("client_loop: send disconnect: Broken pipe")) if (message.Contains("client_loop: send disconnect: Broken pipe"))
{ {
Debug.Console(0, this, Debug.ErrorLogLevel.Error, Debug.Console(1, this, Debug.ErrorLogLevel.Error,
"Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected."); "Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected.");
return; return;
@@ -1077,24 +1058,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
case "phonebooklistresult": case "phonebooklistresult":
{ {
// This result will always be the complete contents of the directory and never
// A subset of the results via a search
JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook);
var directoryResults =
zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts);
if (!PhonebookSyncState.InitialSyncComplete) if (!PhonebookSyncState.InitialSyncComplete)
{ {
PhonebookSyncState.InitialPhonebookFoldersReceived(); PhonebookSyncState.InitialPhonebookFoldersReceived();
PhonebookSyncState.PhonebookRootEntriesReceived(); PhonebookSyncState.PhonebookRootEntriesReceived();
PhonebookSyncState.SetPhonebookHasFolders(false); PhonebookSyncState.SetPhonebookHasFolders(true);
PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count);
} }
var directoryResults = if (directoryResults.ResultsFolderId != "root")
zStatus.Phonebook.ConvertZoomContactsToGeneric(Status.Phonebook.Contacts); {
directoryResults.ResultsFolderId = "root";
}
DirectoryRoot = directoryResults; DirectoryRoot = directoryResults;
_currentDirectoryResult = DirectoryRoot; CurrentDirectoryResult = directoryResults;
OnDirectoryResultReturned(directoryResults);
break; break;
} }
@@ -1119,6 +1106,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (participant != null) if (participant != null)
{ {
Debug.Console(1, this,
"[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} **********************************",
participant.Event);
Debug.Console(1, this,
"[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} - UserId: {1} Name: {2} IsHost: {3}",
participant.Event, participant.UserId, participant.UserName, participant.IsHost);
switch (participant.Event) switch (participant.Event)
{ {
case "ZRCUserChangedEventUserInfoUpdated": case "ZRCUserChangedEventUserInfoUpdated":
@@ -1144,10 +1138,35 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
break; break;
case "ZRCUserChangedEventJoinedMeeting": case "ZRCUserChangedEventJoinedMeeting":
{
var existingParticipant =
Status.Call.Participants.FirstOrDefault(p => p.UserId.Equals(participant.UserId));
if (existingParticipant != null)
{
Debug.Console(1, this,
"[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...updating matching UserId participant with UserId: {1} UserName: {2}",
participant.Event, participant.UserId, participant.UserName);
JsonConvert.PopulateObject(responseObj.ToString(), existingParticipant);
}
else
{
Debug.Console(1, this,
"[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ...adding participant with UserId: {1} UserName: {2}",
participant.Event, participant.UserId, participant.UserName);
Status.Call.Participants.Add(participant); Status.Call.Participants.Add(participant);
}
break; break;
} }
} }
Debug.Console(1, this,
"[DeserializeResponse] zCommands.listparticipantresult - participant.event: {0} ***********************************",
participant.Event);
}
} }
break; break;
} }
@@ -1157,7 +1176,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Status.Call.Participants); Status.Call.Participants);
Participants.CurrentParticipants = participants; Participants.CurrentParticipants = participants;
PrintCurrentCallParticipants(); PrintCurrentCallParticipants();
break; break;
@@ -1250,7 +1268,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
Direction = eCodecCallDirection.Incoming, Direction = eCodecCallDirection.Incoming,
Status = eCodecCallStatus.Ringing, Status = eCodecCallStatus.Ringing,
Type = eCodecCallType.Unknown, Type = eCodecCallType.Video,
Name = incomingCall.callerName, Name = incomingCall.callerName,
Id = incomingCall.callerJID Id = incomingCall.callerJID
}; };
@@ -1291,6 +1309,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var disconnectEvent = var disconnectEvent =
JsonConvert.DeserializeObject<zEvent.CallDisconnect>(responseObj.ToString()); JsonConvert.DeserializeObject<zEvent.CallDisconnect>(responseObj.ToString());
Debug.Console(1, this,
"[DeserializeResponse] zEvent.calldisconnect ********************************************");
Debug.Console(1, this, "[DeserializeResponse] zEvent.calldisconnect - disconnectEvent.Successful: {0}",
disconnectEvent.Successful);
if (disconnectEvent.Successful) if (disconnectEvent.Successful)
{ {
if (ActiveCalls.Count > 0) if (ActiveCalls.Count > 0)
@@ -1299,15 +1322,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (activeCall != null) if (activeCall != null)
{ {
Debug.Console(1, this,
"[DeserializeResponse] zEvent.calldisconnect - ActiveCalls.Count: {0} activeCall.Id: {1}, activeCall.Number: {2} activeCall.Name: {3}, activeCall.IsActive: {4}",
ActiveCalls.Count, activeCall.Id, activeCall.Number, activeCall.Name, activeCall.IsActiveCall);
activeCall.Status = eCodecCallStatus.Disconnected; activeCall.Status = eCodecCallStatus.Disconnected;
OnCallStatusChange(activeCall); OnCallStatusChange(activeCall);
} }
} }
var emptyList = new List<Participant>();
Participants.CurrentParticipants = emptyList;
} }
Debug.Console(1, this,
"[DeserializeResponse] zEvent.calldisconnect ********************************************");
UpdateCallStatus(); UpdateCallStatus();
break; break;
} }
@@ -1323,7 +1350,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
case "meetingneedspassword": case "meetingneedspassword":
{ {
// TODO: notify user to enter a password var meetingNeedsPassword =
responseObj.ToObject<zEvent.MeetingNeedsPassword>();
if (meetingNeedsPassword.NeedsPassword)
{
var prompt = "Password required to join this meeting. Please enter the meeting password.";
OnPasswordRequired(meetingNeedsPassword.WrongAndRetry, false, false, prompt);
}
else
{
OnPasswordRequired(false, false, true, "");
}
break; break;
} }
case "needwaitforhost": case "needwaitforhost":
@@ -1358,20 +1398,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
var status = responseObj.ToObject<zEvent.PinStatusOfScreenNotification>(); var status = responseObj.ToObject<zEvent.PinStatusOfScreenNotification>();
Debug.Console(1, this, "Pin Status notification for UserId: {0}, ScreenIndex: {1}", status.PinnedUserId, status.ScreenIndex); Debug.Console(1, this, "Pin Status notification for UserId: {0}, ScreenIndex: {1}", status.PinnedUserId,
status.ScreenIndex);
Participant alreadyPinnedParticipant = null; Participant alreadyPinnedParticipant = null;
// Check for a participant already pinned to the same screen index. // Check for a participant already pinned to the same screen index.
if (status.PinnedUserId > 0) if (status.PinnedUserId > 0)
{ {
alreadyPinnedParticipant = Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); alreadyPinnedParticipant =
Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex));
// Make sure that the already pinned participant isn't the same ID as for this message. If true, clear the pinned fb. // Make sure that the already pinned participant isn't the same ID as for this message. If true, clear the pinned fb.
if (alreadyPinnedParticipant != null && alreadyPinnedParticipant.UserId != status.PinnedUserId) if (alreadyPinnedParticipant != null && alreadyPinnedParticipant.UserId != status.PinnedUserId)
{ {
Debug.Console(1, this, "Participant: {0} with id: {1} already pinned to screenIndex {2}. Clearing pinned fb.", Debug.Console(1, this, "Participant: {0} with id: {1} already pinned to screenIndex {2}. Clearing pinned fb.",
alreadyPinnedParticipant.Name, alreadyPinnedParticipant.UserId, alreadyPinnedParticipant.ScreenIndexIsPinnedToFb); alreadyPinnedParticipant.Name, alreadyPinnedParticipant.UserId,
alreadyPinnedParticipant.ScreenIndexIsPinnedToFb);
alreadyPinnedParticipant.IsPinnedFb = false; alreadyPinnedParticipant.IsPinnedFb = false;
alreadyPinnedParticipant.ScreenIndexIsPinnedToFb = -1; alreadyPinnedParticipant.ScreenIndexIsPinnedToFb = -1;
} }
@@ -1386,16 +1429,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
else else
{ {
participant = Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex)); participant =
Participants.CurrentParticipants.FirstOrDefault(p => p.ScreenIndexIsPinnedToFb.Equals(status.ScreenIndex));
if (participant == null && alreadyPinnedParticipant == null) if (participant == null && alreadyPinnedParticipant == null)
{ {
Debug.Console(1, this, "no matching participant found by pinned_user_id: {0} or screen_index: {1}", status.PinnedUserId, status.ScreenIndex); Debug.Console(1, this, "no matching participant found by pinned_user_id: {0} or screen_index: {1}",
status.PinnedUserId, status.ScreenIndex);
return; return;
} }
else if (participant != null) else if (participant != null)
{ {
Debug.Console(2, this, "Unpinning {0} with id: {1} from screen index: {2}", participant.Name, participant.UserId, status.ScreenIndex); Debug.Console(2, this, "Unpinning {0} with id: {1} from screen index: {2}", participant.Name,
participant.UserId, status.ScreenIndex);
participant.IsPinnedFb = false; participant.IsPinnedFb = false;
participant.ScreenIndexIsPinnedToFb = -1; participant.ScreenIndexIsPinnedToFb = -1;
} }
@@ -1440,6 +1486,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
JsonConvert.PopulateObject(responseObj.ToString(), Status.Call); JsonConvert.PopulateObject(responseObj.ToString(), Status.Call);
Debug.Console(1, this,
"[DeserializeResponse] zStatus.call - Status.Call.Info.meeting_id: {0} Status.Call.Info.meeting_list_item.meetingName: {1}",
Status.Call.Info.meeting_id, Status.Call.Info.meeting_list_item.meetingName);
foreach (var participant in Status.Call.Participants)
{
Debug.Console(1, this,
"[DeserializeResponse] zStatus.call - Status.Call.Participants participant.UserId: {0} participant.UserName: {1}",
participant.UserId, participant.UserName);
}
UpdateCallStatus(); UpdateCallStatus();
break; break;
@@ -1535,18 +1591,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
} }
/// <summary>
/// Retrieves the current call participants list
/// </summary>
public void GetCurrentCallParticipants()
{
SendText("zCommand Call ListParticipants");
}
/// <summary>
/// Prints the current call particiapnts list
/// </summary>
public void PrintCurrentCallParticipants() public void PrintCurrentCallParticipants()
{ {
if (Debug.Level <= 0) if (Debug.Level <= 0) return;
{
return;
}
Debug.Console(1, this, "*************************** Call Participants **************************"); Debug.Console(1, this, "*************************** Call Participants **************************");
foreach (var participant in Participants.CurrentParticipants) foreach (var participant in Participants.CurrentParticipants)
{ {
Debug.Console(1, this, "Name: {0} Audio: {1} IsHost: {2}", participant.Name, Debug.Console(1, this, "UserId: {3} Name: {0} Audio: {1} IsHost: {2}",
participant.AudioMuteFb, participant.IsHost); participant.Name, participant.AudioMuteFb, participant.IsHost, participant.UserId);
} }
Debug.Console(1, this, "************************************************************************"); Debug.Console(1, this, "************************************************************************");
} }
@@ -1566,16 +1630,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void UpdateCallStatus() private void UpdateCallStatus()
{ {
Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}",
Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); Status.Call != null ? Status.Call.Status.ToString() : "no call");
if (Status.Call != null) if (Status.Call != null)
{ {
var callStatus = Status.Call.Status; var callStatus = Status.Call.Status;
// If not currently in a meeting, intialize the call object // If not crrently in a meeting, intialize the call object
if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING) if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING)
{ {
Debug.Console(1, this, "Creating new Status.Call object"); Debug.Console(1, this, "[UpdateCallStatus] Creating new Status.Call object");
Status.Call = new zStatus.Call {Status = callStatus}; Status.Call = new zStatus.Call {Status = callStatus};
OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected}); OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected});
@@ -1600,22 +1664,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
break; break;
} }
if (!string.IsNullOrEmpty(Status.Call.Info.meeting_id))
{
var newCall = new CodecActiveCallItem var newCall = new CodecActiveCallItem
{ {
Name = Status.Call.Info.meeting_list_item.meetingName, Name = Status.Call.Info.meeting_list_item.meetingName,
Number = Status.Call.Info.meeting_list_item.meetingNumber,
Id = Status.Call.Info.meeting_id, Id = Status.Call.Info.meeting_id,
Status = newStatus Status = newStatus,
Type = eCodecCallType.Video,
}; };
ActiveCalls.Add(newCall); ActiveCalls.Add(newCall);
Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", Debug.Console(1, this, "[UpdateCallStatus] IF w/ meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}",
Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count);
OnCallStatusChange(newCall); OnCallStatusChange(newCall);
} }
else
{
Debug.Console(1, this, "[UpdateCallStatus] IF w/o meeting_id AcitveCalls.Count == {1} - Current Call Status: {0}",
Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count);
}
}
} }
else else
{ {
@@ -1631,14 +1703,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
break; break;
} }
Debug.Console(1, this, "[UpdateCallStatus] Current Call Status: {0}", Debug.Console(1, this, "[UpdateCallStatus] ELSE ActiveCalls.Count == {1} - Current Call Status: {0}",
Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); Status.Call != null ? Status.Call.Status.ToString() : "no call", ActiveCalls.Count);
OnCallStatusChange(existingCall); OnCallStatusChange(existingCall);
} }
} }
Debug.Console(1, this, "*************************** Active Calls ********************************"); Debug.Console(1, this, "[UpdateCallStatus] Active Calls ------------------------------");
// Clean up any disconnected calls left in the list // Clean up any disconnected calls left in the list
for (int i = 0; i < ActiveCalls.Count; i++) for (int i = 0; i < ActiveCalls.Count; i++)
@@ -1646,26 +1718,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var call = ActiveCalls[i]; var call = ActiveCalls[i];
Debug.Console(1, this, Debug.Console(1, this,
@"Name: {0} @"ID: {1}
ID: {1} Number: {5}
Name: {0}
IsActive: {2} IsActive: {2}
Status: {3} Status: {3}
Direction: {4}", call.Name, call.Id, call.IsActiveCall, call.Status, call.Direction); Direction: {4}
IsActiveCall: {6}", call.Name, call.Id, call.IsActiveCall, call.Status, call.Direction, call.Number,
call.IsActiveCall);
if (!call.IsActiveCall) if (!call.IsActiveCall)
{ {
Debug.Console(1, this, "***** Removing Inactive Call: {0} *****", call.Name); Debug.Console(1, this, "[UpdateCallStatus] Removing Inactive call.Id: {1} call.Name: {0}", call.Name, call.Id);
ActiveCalls.Remove(call); ActiveCalls.Remove(call);
} }
} }
Debug.Console(1, this, "**************************************************************************"); Debug.Console(1, this, "[UpdateCallStatus] Active Calls ------------------------------");
//clear participants list after call cleanup //clear participants list after call cleanup
if (ActiveCalls.Count == 0)
{
var emptyList = new List<Participant>(); var emptyList = new List<Participant>();
Participants.CurrentParticipants = emptyList; Participants.CurrentParticipants = emptyList;
} if (ActiveCalls.Count > 0) GetCurrentCallParticipants();
} }
protected override void OnCallStatusChange(CodecActiveCallItem item) protected override void OnCallStatusChange(CodecActiveCallItem item)
@@ -1673,7 +1746,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
base.OnCallStatusChange(item); base.OnCallStatusChange(item);
Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}", Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}",
Status.Call != null ? Status.Call.Sharing.State.ToString() : "no call"); Status.Call != null ? Status.Call.Status.ToString() : "no call");
if (_props.AutoDefaultLayouts) if (_props.AutoDefaultLayouts)
{ {
@@ -1718,13 +1791,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public override void MuteOff() public override void MuteOff()
{ {
Debug.Console(2, this, "Unmuting to previous level: {0}", _previousVolumeLevel);
SetVolume((ushort) _previousVolumeLevel); SetVolume((ushort) _previousVolumeLevel);
} }
public override void MuteOn() public override void MuteOn()
{ {
_previousVolumeLevel = Configuration.Audio.Output.Volume; // Store the previous level for recall
SetVolume(0); SetVolume(0);
} }
@@ -1826,13 +1898,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
layoutsCodec.AvailableLayoutsChanged += (o, a) => layoutsCodec.AvailableLayoutsChanged += (o, a) =>
{ {
trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery
== (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery)); ==
(a.AvailableLayouts &
zConfiguration.eLayoutStyle.Gallery));
trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker
== (a.AvailableLayouts & zConfiguration.eLayoutStyle.Speaker)); ==
(a.AvailableLayouts &
zConfiguration.eLayoutStyle.Speaker));
trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip
== (a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip)); ==
(a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip));
trilist.SetBool(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll trilist.SetBool(joinMap.LayoutShareAllIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.ShareAll
== (a.AvailableLayouts & zConfiguration.eLayoutStyle.ShareAll)); ==
(a.AvailableLayouts &
zConfiguration.eLayoutStyle.ShareAll));
// pass the names used to set the layout through the bridge // pass the names used to set the layout through the bridge
trilist.SetString(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery.ToString()); trilist.SetString(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery.ToString());
@@ -1843,10 +1922,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
trilist.SetSigFalseAction(joinMap.SwapContentWithThumbnail.JoinNumber, () => layoutsCodec.SwapContentWithThumbnail()); trilist.SetSigFalseAction(joinMap.SwapContentWithThumbnail.JoinNumber, () => layoutsCodec.SwapContentWithThumbnail());
layoutsCodec.CanSwapContentWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]); layoutsCodec.CanSwapContentWithThumbnailFeedback.LinkInputSig(
layoutsCodec.ContentSwappedWithThumbnailFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SwapContentWithThumbnail.JoinNumber]); trilist.BooleanInput[joinMap.CanSwapContentWithThumbnail.JoinNumber]);
layoutsCodec.ContentSwappedWithThumbnailFeedback.LinkInputSig(
trilist.BooleanInput[joinMap.SwapContentWithThumbnail.JoinNumber]);
layoutsCodec.LayoutViewIsOnFirstPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnFirstPage.JoinNumber]); layoutsCodec.LayoutViewIsOnFirstPageFeedback.LinkInputSig(
trilist.BooleanInput[joinMap.LayoutIsOnFirstPage.JoinNumber]);
layoutsCodec.LayoutViewIsOnLastPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnLastPage.JoinNumber]); layoutsCodec.LayoutViewIsOnLastPageFeedback.LinkInputSig(trilist.BooleanInput[joinMap.LayoutIsOnLastPage.JoinNumber]);
trilist.SetSigFalseAction(joinMap.LayoutTurnToNextPage.JoinNumber, () => layoutsCodec.LayoutTurnNextPage()); trilist.SetSigFalseAction(joinMap.LayoutTurnToNextPage.JoinNumber, () => layoutsCodec.LayoutTurnNextPage());
trilist.SetSigFalseAction(joinMap.LayoutTurnToPreviousPage.JoinNumber, () => layoutsCodec.LayoutTurnPreviousPage()); trilist.SetSigFalseAction(joinMap.LayoutTurnToPreviousPage.JoinNumber, () => layoutsCodec.LayoutTurnPreviousPage());
@@ -1973,9 +2055,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public override void Dial(string number) public override void Dial(string number)
{ {
_lastDialedMeetingNumber = number;
SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number)); SendText(string.Format("zCommand Dial Join meetingNumber: {0}", number));
} }
/// <summary>
/// Dials a meeting with a password
/// </summary>
/// <param name="number"></param>
/// <param name="password"></param>
public void Dial(string number, string password)
{
Debug.Console(2, this, "Dialing meeting number: {0} with password: {1}", number, password);
SendText(string.Format("zCommand Dial Join meetingNumber: {0} password: {1}", number, password));
}
/// <summary> /// <summary>
/// Invites a contact to either a new meeting (if not already in a meeting) or the current meeting. /// Invites a contact to either a new meeting (if not already in a meeting) or the current meeting.
/// Currently only invites a single user /// Currently only invites a single user
@@ -2022,7 +2116,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <param name="result"></param> /// <param name="result"></param>
private void OnDirectoryResultReturned(CodecDirectory result) private void OnDirectoryResultReturned(CodecDirectory result)
{ {
CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); try
{
Debug.Console(2, this, "OnDirectoryResultReturned");
var directoryResult = new CodecDirectory();
// If result is Root, create a copy and filter out contacts whose parent folder is not root
if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue)
{
Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display");
directoryResult.ResultsFolderId = result.ResultsFolderId;
directoryResult.AddFoldersToDirectory(result.Folders);
directoryResult.AddContactsToDirectory(
result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList());
}
else
{
directoryResult = result;
}
Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0}",
!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
// This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology
var handler = DirectoryResultReturned; var handler = DirectoryResultReturned;
@@ -2030,10 +2146,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
handler(this, new DirectoryEventArgs handler(this, new DirectoryEventArgs
{ {
Directory = result, Directory = directoryResult,
DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue
}); });
} }
}
catch (Exception e)
{
Debug.Console(2, this, "Error: {0}", e);
}
//PrintDirectory(result); //PrintDirectory(result);
} }
@@ -2049,6 +2170,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
foreach (var cam in Status.Cameras) foreach (var cam in Status.Cameras)
{ {
// Known Issue:
// Crestron UC engine systems seem to report an item in the cameras list that represnts the USB bridge device.
// If we know the name and it's reliably consistent, we could ignore it here...
if (cam.Name.IndexOf("HD-CONV-USB") > -1)
{
// Skip this as it's the Crestron USB box, not a real camera
continue;
}
var camera = new ZoomRoomCamera(cam.id, cam.Name, this); var camera = new ZoomRoomCamera(cam.id, cam.Name, this);
Cameras.Add(camera); Cameras.Add(camera);
@@ -2151,7 +2282,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
#region IHasParticipantPinUnpin Members #region IHasParticipantPinUnpin Members
private Func<int> NumberOfScreensFeedbackFunc { get { return () => Status.NumberOfScreens.NumOfScreens; } } private Func<int> NumberOfScreensFeedbackFunc
{
get { return () => Status.NumberOfScreens.NumOfScreens; }
}
public IntFeedback NumberOfScreensFeedback { get; private set; } public IntFeedback NumberOfScreensFeedback { get; private set; }
@@ -2293,6 +2427,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
#endregion #endregion
// TODO: #714 [ ] Implementation of IHasSelfviewPipSize // TODO: #714 [ ] Implementation of IHasSelfviewPipSize
#region Implementation of IHasSelfviewPipSize #region Implementation of IHasSelfviewPipSize
private CodecCommandWithLabel _currentSelfviewPipSize; private CodecCommandWithLabel _currentSelfviewPipSize;
@@ -2334,14 +2469,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
p => p.Command.ToLower().Equals(Configuration.Call.Layout.Size.ToString().ToLower())); p => p.Command.ToLower().Equals(Configuration.Call.Layout.Size.ToString().ToLower()));
} }
#endregion #endregion
#region Implementation of IHasPhoneDialing #region Implementation of IHasPhoneDialing
private Func<bool> PhoneOffHookFeedbackFunc { get { return () => Status.PhoneCall.OffHook; } } private Func<bool> PhoneOffHookFeedbackFunc
private Func<string> CallerIdNameFeedbackFunc { get { return () => Status.PhoneCall.PeerDisplayName; } } {
private Func<string> CallerIdNumberFeedbackFunc { get { return () => Status.PhoneCall.PeerNumber; } } get { return () => Status.PhoneCall.OffHook; }
}
private Func<string> CallerIdNameFeedbackFunc
{
get { return () => Status.PhoneCall.PeerDisplayName; }
}
private Func<string> CallerIdNumberFeedbackFunc
{
get { return () => Status.PhoneCall.PeerNumber; }
}
public BoolFeedback PhoneOffHookFeedback { get; private set; } public BoolFeedback PhoneOffHookFeedback { get; private set; }
public StringFeedback CallerIdNameFeedback { get; private set; } public StringFeedback CallerIdNameFeedback { get; private set; }
@@ -2368,10 +2513,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public event EventHandler<LayoutInfoChangedEventArgs> AvailableLayoutsChanged; public event EventHandler<LayoutInfoChangedEventArgs> AvailableLayoutsChanged;
private Func<bool> LayoutViewIsOnFirstPageFeedbackFunc { get { return () => Status.Layout.is_In_First_Page; } } private Func<bool> LayoutViewIsOnFirstPageFeedbackFunc
private Func<bool> LayoutViewIsOnLastPageFeedbackFunc { get { return () => Status.Layout.is_In_Last_Page; } } {
private Func<bool> CanSwapContentWithThumbnailFeedbackFunc { get { return () => Status.Layout.can_Switch_Floating_Share_Content; } } get { return () => Status.Layout.is_In_First_Page; }
private Func<bool> ContentSwappedWithThumbnailFeedbackFunc { get { return () => Configuration.Call.Layout.ShareThumb; } } }
private Func<bool> LayoutViewIsOnLastPageFeedbackFunc
{
get { return () => Status.Layout.is_In_Last_Page; }
}
private Func<bool> CanSwapContentWithThumbnailFeedbackFunc
{
get { return () => Status.Layout.can_Switch_Floating_Share_Content; }
}
private Func<bool> ContentSwappedWithThumbnailFeedbackFunc
{
get { return () => Configuration.Call.Layout.ShareThumb; }
}
public BoolFeedback LayoutViewIsOnFirstPageFeedback { get; private set; } public BoolFeedback LayoutViewIsOnFirstPageFeedback { get; private set; }
@@ -2441,7 +2601,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
if (CanSwapContentWithThumbnailFeedback.BoolValue) if (CanSwapContentWithThumbnailFeedback.BoolValue)
{ {
var oppositeValue = ContentSwappedWithThumbnailFeedback.BoolValue ? "on" : "off"; // Get the value based on the opposite of the current state var oppositeValue = ContentSwappedWithThumbnailFeedback.BoolValue ? "on" : "off";
// Get the value based on the opposite of the current state
// TODO: #697 [*] Need to verify the ternary above and make sure that the correct on/off value is being send based on the true/false value of the feedback // TODO: #697 [*] Need to verify the ternary above and make sure that the correct on/off value is being send based on the true/false value of the feedback
// to toggle the state // to toggle the state
SendText(String.Format("zConfiguration Call Layout ShareThumb: {0}", oppositeValue)); SendText(String.Format("zConfiguration Call Layout ShareThumb: {0}", oppositeValue));
@@ -2480,7 +2641,50 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public void LocalLayoutToggle() public void LocalLayoutToggle()
{ {
throw new NotImplementedException(); var currentLayout = LocalLayoutFeedback.StringValue;
var eCurrentLayout = (int) Enum.Parse(typeof (zConfiguration.eLayoutStyle), currentLayout, true);
var nextLayout = GetNextLayout(eCurrentLayout);
if (nextLayout != zConfiguration.eLayoutStyle.None)
{
SetLayout(nextLayout);
}
}
/// <summary>
/// Tries to get the next available layout
/// </summary>
/// <param name="currentLayout"></param>
/// <returns></returns>
private zConfiguration.eLayoutStyle GetNextLayout(int currentLayout)
{
if (AvailableLayouts == zConfiguration.eLayoutStyle.None)
{
return zConfiguration.eLayoutStyle.None;
}
zConfiguration.eLayoutStyle nextLayout;
if (((zConfiguration.eLayoutStyle) currentLayout & zConfiguration.eLayoutStyle.ShareAll) ==
zConfiguration.eLayoutStyle.ShareAll)
{
nextLayout = zConfiguration.eLayoutStyle.Gallery;
}
else
{
nextLayout = (zConfiguration.eLayoutStyle) (currentLayout << 1);
}
if ((AvailableLayouts & nextLayout) == nextLayout)
{
return nextLayout;
}
else
{
return GetNextLayout((int) nextLayout);
}
} }
public void LocalLayoutToggleSingleProminent() public void LocalLayoutToggleSingleProminent()
@@ -2495,6 +2699,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
#endregion #endregion
#region IPasswordPrompt Members
public event EventHandler<PasswordPromptEventArgs> PasswordRequired;
public void SubmitPassword(string password)
{
Debug.Console(2, this, "Password Submitted: {0}", password);
Dial(_lastDialedMeetingNumber, password);
}
void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message)
{
var handler = PasswordRequired;
if (handler != null)
{
handler(this, new PasswordPromptEventArgs(lastAttemptIncorrect, loginFailed, loginCancelled, message));
}
}
#endregion
} }
/// <summary> /// <summary>

View File

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

View File

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