Compare commits

..

125 Commits

Author SHA1 Message Date
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
Neil Dorin
f4ac4e6319 Minor updates to resolve oddities with ZoomRoom and TSW UI drivers (call status) 2021-07-28 16:38:20 -06:00
Andrew Welker
b026174cd2 Merge branch 'main' into release/1.9.2 2021-07-28 15:47:46 -06:00
Neil Dorin
66ff6b2e07 Brings in another small zoom update from @jkdevito 2021-07-28 15:33:04 -06:00
Neil Dorin
e7bbfbd40a Update to add populate call Id and Name properties to allow proper removal of inactive calls 2021-07-28 15:27:47 -06:00
Neil Dorin
eec86fde48 Updates incorrect path for ZoomRoom feedback exclusions and adds toll_free_callinList 2021-07-28 15:23:57 -06:00
Neil Dorin
7b57ce439e #761 Adds support for x70 series touchpanels 2021-07-28 14:47:17 -06:00
Andrew Welker
5d120391a5 Merge pull request #752 from PepperDash/feature/ndorin-patch-1
Adds a prompt to capture affected version
2021-07-21 13:16:59 -06:00
Neil Dorin
db5aa319ec Adds a prompt to capture affected version 2021-07-20 16:49:03 -06:00
Neil Dorin
10f5516a5a Merge pull request #749 from PepperDash/feature/occ-aggregator
Update Occupancy Aggregator to be real device
2021-07-19 15:43:58 -06:00
Andrew Welker
45e6dff26d fix: update access level for config constructor 2021-07-19 15:10:03 -06:00
Andrew Welker
10129b8178 feat: Add post activation action for aggregator 2021-07-19 15:09:37 -06:00
Andrew Welker
9128e108f7 feat: Add clear method to BoolOutputLogical
and do a bit of refactoring
2021-07-19 15:09:03 -06:00
Andrew Welker
760ec8be92 feat: Add occupancy aggregator factory and config 2021-07-19 14:08:57 -06:00
Andrew Welker
bbcdd3e179 Merge pull request #747 from PepperDash/feature/C2N-IO-add
Add C2NIoController to csproj
2021-07-19 14:06:33 -06:00
Andrew Welker
7a649f4ea8 Merge branch 'development' into feature/C2N-IO-add 2021-07-19 13:48:43 -06:00
Andrew Welker
6946946c12 chore: Add c2nIoController to csproj 2021-07-19 13:47:17 -06:00
Neil Dorin
dca73e1508 Merge pull request #745 from PepperDash/feature/C2N-IO-add
Add C2N-IO
2021-07-19 11:55:15 -06:00
Andrew Welker
990090e1de feat: Add support for C2N-IO 2021-07-19 10:29:30 -06:00
Andrew Welker
3b843104d8 Merge pull request #738 from PepperDash/feature/room-combining
Feature/room combining
2021-07-13 22:14:42 -06:00
Neil Dorin
a37814ab3c #736 adds IEssentialsHuddleVtc1Room and refactors to use interface rather than EssentialsHudleVtc1Room 2021-07-12 21:49:54 -06:00
Neil Dorin
2181410927 #736 Adds IEssentialsRoom and IEssentialsHuddleSpaceRoom interfaces
Refactors all references to EssentialsRoomBase and EssentialsHuddleSpaceRoom to use the new interfaces instead
2021-07-12 17:22:36 -06:00
Andrew Welker
d4191ceb75 Merge pull request #735 from PepperDash/hotfix/zip-release-upload
Hotfix/zip release upload
2021-07-08 12:04:57 -06:00
Andrew Welker
5f6d15c6c0 Merge branch 'development' into hotfix/zip-release-upload 2021-07-08 11:41:40 -06:00
Andrew Welker
4cc40227fd Merge pull request #734 from PepperDash/hotfix/zip-release-upload
ci: Remove condition on upload to release
2021-07-08 11:41:32 -06:00
Andrew Welker
d0dbbe095f ci: Remove condition on upload to release 2021-07-08 11:16:41 -06:00
Andrew Welker
c7180db2b7 Merge pull request #730 from PepperDash/feature/update-ihasscheduleawareness
Feature/update ihasscheduleawareness
2021-07-03 00:39:29 -06:00
Neil Dorin
d95ee27979 #728 corrects casing of folder name in Global.FilePathPrefix at startup 2021-07-02 15:01:51 -06:00
Neil Dorin
e964172200 #729 Updates to get CheckSchedule method working as designed 2021-07-02 15:01:17 -06:00
Neil Dorin
840934502b Working on getting meeting change events to trigger properly 2021-06-29 17:35:22 -06:00
Neil Dorin
a76f4c15dc Updates to IHasScheduleAwareness 2021-06-29 09:47:56 -06:00
Neil Dorin
b19e2e38ad Merge pull request #727 from PepperDash/hotfix/add-eisc-server-client-options-to-eiscapiadvanced-factory
Hotfix/add eisc server client options to eiscapiadvanced factory
2021-06-24 16:53:14 -06:00
Neil Dorin
9a7fe553f9 Merge branch 'development' into hotfix/add-eisc-server-client-options-to-eiscapiadvanced-factory 2021-06-24 16:35:29 -06:00
Neil Dorin
e6ecaf3a1e Merge pull request #726 from PepperDash/hotfix/add-eisc-server-client-options-to-eiscapiadvanced-factory
adds new type options to use EISCClient and EISCServer in eiscapiadvanced
2021-06-24 16:35:18 -06:00
Andrew Welker
895b76a0cd Merge pull request #723 from PepperDash/hotfix/zoom-room-views
Hotfix/zoom room views
2021-06-24 13:28:48 -06:00
Neil Dorin
5c9996e728 adds new type options to use EISCClient and EISCServer in eiscapiadvanced 2021-06-17 13:49:09 -06:00
Andrew Welker
0cc2328276 Merge branch 'development' into hotfix/zoom-room-views 2021-06-17 10:03:42 -06:00
Andrew Welker
8fadfa98f2 Merge pull request #724 from PepperDash/hotfix/zoom-room-views
Hotfix/zoom room views
2021-06-17 10:02:17 -06:00
Andrew Welker
1ccf54003f Merge branch 'main' into hotfix/zoom-room-views 2021-06-17 09:32:04 -06:00
Neil Dorin
54769ce270 Merge pull request #722 from PepperDash/hotfix/plugin-loading
Hotfix/plugin loading
2021-06-16 17:20:57 -06:00
Andrew Welker
6b85323949 Merge branch 'development' into hotfix/plugin-loading 2021-06-16 15:17:52 -06:00
Andrew Welker
319d8f99c5 Merge pull request #721 from PepperDash/hotfix/plugin-loading
adds check for abstract class before attempting to create instance
2021-06-16 15:17:32 -06:00
Neil Dorin
cc742f4291 adds check for abstract class before attempting to create instance 2021-06-16 13:11:45 -06:00
Jason DeVito
6beff106ec Updated packages.config to track latest PepperDash Core release. Updated ZoomRoom LinkZoomRoomToApi to update the bridge when it comes online. 2021-06-10 17:45:23 -05:00
Neil Dorin
cb35aa13f5 lets it fall through conditions to fire the ParticipantsChanged event if an already pinned participant is found 2021-06-09 17:55:55 -06:00
Neil Dorin
b71523bd2d Adds condition to not check for already pinned participant if incoming message has user id < 0 2021-06-09 17:38:50 -06:00
Neil Dorin
0c56da112c Changes to respond to new pinned participant message by clearing out already pinned participant fb first. 2021-06-09 17:07:25 -06:00
Neil Dorin
08f4d8e9a2 Attempts to unpin participant from same screenIndex if one is already pinned. 2021-06-09 16:57:42 -06:00
Neil Dorin
25e7e9634a updates PD Core version to include xsig token fixes 2021-06-09 16:56:56 -06:00
Neil Dorin
7ac3f81ea5 Initialize SreenIndexIsPinnedToFb to -1. Adds debugging for xsig tokens 2021-06-09 16:14:18 -06:00
Neil Dorin
1c06e8381b Fixed inverted video mute FB and adds debug statements to help see participant pin status 2021-06-09 13:30:36 -06:00
Jason DeVito
f5305197b3 Updates to LinkZoomRoomApi method 2021-06-09 13:37:01 -05:00
Jason DeVito
1805ebaf0f Converted ZoomRoom Layout Size properties and methods to interface, IHasSelfviewSize, following the patterns implemented for IHasSelfviewPosition and SelfviewPipPosition. 2021-06-08 17:56:00 -05:00
Jason DeVito
ca8207f2bd Removed Layout Position properties and methods. Using SelfviewPipPosition properties and methods. 2021-06-08 15:20:42 -05:00
Neil Dorin
4e81859695 Merge pull request #719 from PepperDash/bugfix/setdevicestreamdebug-fix
Bugfix/setdevicestreamdebug fix
2021-06-08 13:45:08 -06:00
Jason DeVito
655bb954fa Updated IHasCodecLayouts and ZoomRoom to test feedback of Layout Size and Layout Position. 2021-06-08 14:38:33 -05:00
Andrew Welker
1ebacf3f0f Fix formatting issue 2021-06-08 12:12:59 -06:00
Andrew Welker
7de0251188 add ConvertType method to convert type
This method should allow for using a string value in place of an enum as a parameter. Integers will still fail.
2021-06-08 11:44:09 -06:00
Jason DeVito
492e593263 Updated IHasCodecLayouts to implement Layout Position selection and feedback, updated bridge map to map Layout Position signals. Updated ZoomRoom to implement Layout Position selection and feedback. 2021-06-07 22:22:00 -05:00
Jason DeVito
afe2046c81 Added methods to select Call Layout Size. 2021-06-07 14:45:40 -05:00
Neil Dorin
98d3a4a2fa Merge pull request #713 from PepperDash/release/1.9.0
1.9.0
2021-05-25 14:48:52 -06:00
Andrew Welker
1702c69b73 Merge branch 'main' into release/1.9.0 2021-05-25 14:37:27 -06:00
Andrew Welker
722d28b1b3 Merge pull request #710 from PepperDash/hotfix/techroom-preset-recall-event
Hotfix/techroom preset recall event
2021-05-24 13:32:46 -06:00
Andrew Welker
ef7da0d7af Merge branch 'development' into hotfix/techroom-preset-recall-event 2021-05-24 13:19:45 -06:00
Neil Dorin
77d8e63a31 Merge pull request #709 from PepperDash/hotfix/techroom-preset-recall-event
Hotfix/techroom preset recall event
2021-05-24 12:59:54 -06:00
Neil Dorin
d2d99d4bfa Merge branch 'main' into hotfix/techroom-preset-recall-event 2021-05-24 12:45:27 -06:00
Neil Dorin
4bd71b04bf Merge pull request #708 from PepperDash/feature/add-zoomroom-participant-actions
Feature/add zoomroom participant actions
2021-05-20 20:34:45 -06:00
Andrew Welker
c5bcd89695 Merge branch 'development' into feature/add-zoomroom-participant-actions 2021-05-20 18:34:58 -06:00
Jason DeVito
c7cc98bff7 Removed old TODO's from VideoCodecBase.cs. Marked TODO's for Issue #697. 2021-05-20 19:32:11 -05:00
Jason DeVito
db60f8f1be ResponseObject.cs updates: Added and tested SortParticipantListtByHandStatus method. Found an issue with HandStatus response, property names include ': ', updated JsonProperty definitions to account for issues with expected returns vs. actual returns. 2021-05-20 15:43:02 -05:00
Andrew Welker
e82efdde2d Merge pull request #707 from PepperDash/hotfix/devjson-overload-fix
fix:(EssentialsCore) Add ability for `devjson` command to handle overloads
2021-05-20 11:04:23 -06:00
Andrew Welker
d00c8bed5f fix:(EssentialsCore) Add ability for devjson command to handle overloads
The `devjson` command needs to ability to handle overloads. With this change, if a method is an overloaded method, the command will get all methods on an object that match the entered method name, then get the first entry in the list of methods that matches the length of the provided parameters list.

This won't work in all cases, as there may be situations where the parameters of the methods have the same length, but different types. In that situation, it's likely that the conversion from `Object` to the desired type will fail, in which case, the command will notify the user that something went wrong.
2021-05-20 10:52:12 -06:00
Andrew Welker
a91af6bd75 Merge pull request #703 from PepperDash/feature/add-rfi-issue-template
Adds RFI Template
2021-05-20 09:22:23 -06:00
Neil Dorin
2d36b80800 Adds CH5 option 2021-05-14 15:46:12 -06:00
Neil Dorin
e152b9a504 Merge branch 'development' into feature/add-rfi-issue-template 2021-05-14 15:05:25 -06:00
Neil Dorin
eac7c91327 Create rfi_request.md 2021-05-13 18:07:03 -06:00
Jason DeVito
ac0d5e59a0 ZoomRoom.cs, commented out Debug statement @ line 874 to remove 'JSON Curly Brace Count:' messages in console when using debug level 2. 2021-05-12 11:27:33 -05:00
Andrew Welker
78be8ec5f2 Merge pull request #701 from PepperDash/feature/reconfigurable-device-write-control
Feature/reconfigurable device write control
2021-05-11 20:22:04 -06:00
Jason Alborough
5fc4ff6027 #700 FIxes issue where ConfigWrite.UpdateDeviceConfig and UpdateRoomConfig do not write config to file 2021-05-11 20:28:15 -04:00
Neil Dorin
63853739f3 Updates object structure to deal with a bug in ZoomRoom 5.6.3 that responds with an incorrect object structure for the layout style property 2021-05-11 17:23:26 -06:00
Jason DeVito
c14193f9ac Updates to VideoCodecControllerJoinMap to fix joins for Participant triggers. Updated ZoomRoomJoinMaps to implement zConfiguration.eLayoutStyle to pass the name across the bridge. 2021-05-11 18:13:18 -05:00
Jason T Alborough
da179c01f5 Fixes UpdateDeviceConfig() 2021-05-11 17:52:26 -04:00
Jason Alborough
0ded3e30f9 Merge branch 'development' into feature/reconfigurable-device-write-control 2021-05-11 15:24:40 -04:00
Jason T Alborough
8d215930d9 Adds WriteControlProperty to ReconfigurableDevice
CameraBase now uses ReconfigurableDevice
2021-05-11 15:20:35 -04:00
Neil Dorin
b4edb021ee #698 merged in join map updates from JKD. Fixed enum bit comparison for available layout feedbacks 2021-05-11 12:23:27 -06:00
Neil Dorin
52caa98f33 Merge branch 'feature/add-zoomroom-layout-controls' into feature/add-zoomroom-participant-actions 2021-05-11 11:10:37 -06:00
Jason DeVito
4e041d1773 Removed unused DecodecParticipantsXSig method. 2021-05-11 11:36:17 -05:00
Jason DeVito
118bd5a54a Updates VideoCodecControllerJoinMap.cs to organize joins. Update to VideoCodecBase.cs UpdateParticipantsXSig. 2021-05-11 11:19:33 -05:00
Jason DeVito
116abbf962 Updates ZoomRoomJoinMap.cs with join numbers. Updated VideoCodecControllerJoinMap.cs to organize the joins in a logical pattern. Update VideoCodecBase to add the maxAnalogs to the logic calculating xsig indexes and offsets. 2021-05-11 08:34:16 -05:00
Neil Dorin
a06333e1c3 Adds temp join numbers for participant actions 2021-05-10 15:38:33 -06:00
Neil Dorin
d937dc14fc #698 Adds actions to toggle audio/video mute and pinning for participants 2021-05-10 15:09:33 -06:00
Neil Dorin
604f4ca22d #698 Adds join objects for participants audio/video mute and pin toggle 2021-05-10 12:58:07 -06:00
Neil Dorin
2d7ad8ba2a #698 Updates to add participant hand raised and pin/unpin 2021-05-07 18:07:25 -06:00
Neil Dorin
e4a3933743 Mostly coded. Needs join numbers for ZoomRoomJoinMap values 2021-05-06 16:54:41 -06:00
Neil Dorin
d6445861f5 Adds IHasZoomRoomLayouts interface. Update zStatus.Layout class to extend NotifiableObject 2021-05-05 21:55:28 -06:00
Jason T Alborough
03b076c8eb Merge pull request #696 from PepperDash/feature/dm-audio-routing-fix
Fixes DM Audio Routing
2021-04-30 15:28:08 -04:00
Andrew Welker
7c58221acc Merge branch 'development' into feature/dm-audio-routing-fix 2021-04-30 13:12:18 -06:00
Andrew Welker
14f7c27b33 Merge pull request #695 from PepperDash/bugfix/discovery-routing-endless-loop
Bugfix/discovery routing endless loop
2021-04-30 13:12:10 -06:00
Jason Alborough
9ea65883b7 Fixes DM Audio Routing 2021-04-30 14:58:39 -04:00
Alex Johnson
9d0020d999 Merge branch 'development' into bugfix/discovery-routing-endless-loop 2021-04-29 13:52:36 -04:00
Alex Johnson
fb44a3b93c Resolves looping in IRouting by adding the device to the tracking list before iterating down further. Adds debug statement to print when this condition occurs - "Skipping input <device> on <router-device>, this was already checked" 2021-04-29 13:44:47 -04:00
Andrew Welker
6b7c5c01f8 Merge pull request #693 from PepperDash/hotfix/console-response-crlf-fixes
Hotfix/console response crlf fixes
2021-04-28 21:58:44 -06:00
Andrew Welker
44c171c8f4 Merge pull request #692 from PepperDash/hotfix/console-response-crlf-fixes
Changes cr to crlf for some console command responses
2021-04-28 09:54:24 -06:00
Neil Dorin
685c344785 #690 fixes incorrect conditional check before firing feedback 2021-04-20 14:38:24 -06:00
67 changed files with 10348 additions and 7337 deletions

View File

@@ -7,6 +7,9 @@ assignees: ''
--- ---
**Was this bug identified in a specific build version?**
Please note the build version where this bug was identified
**Describe the bug** **Describe the bug**
A clear and concise description of what the bug is. A clear and concise description of what the bug is.

27
.github/ISSUE_TEMPLATE/rfi_request.md vendored Normal file
View File

@@ -0,0 +1,27 @@
---
name: Request for Information
about: Request specific information about capabilities of the framework
title: "[RFI]-"
labels: RFI
assignees: ''
---
**What is your request?**
Please provide as much detail as possible.
**What is the intended use case**
- [ ] Essentials Standalone Application
- [ ] Essentials + SIMPL Windows Hybrid
**User Interface Requirements**
- [ ] Not Applicable (logic only)
- [ ] Crestron Smart Graphics Touchpanel
- [ ] Cisco Touch10
- [ ] Mobile Control
- [ ] Crestron CH5 Touchpanel interface
**Additional context**
Add any other context or screenshots about the request here.

View File

@@ -90,7 +90,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Upload the build package to the release # Upload the build package to the release
- name: Upload Release Package - name: Upload Release Package
if: contains(env.VERSION,'-rc-') || contains(env.VERSION,'-hotfix-')
id: upload_release id: upload_release
uses: actions/upload-release-asset@v1 uses: actions/upload-release-asset@v1
with: with:

View File

@@ -131,29 +131,46 @@ namespace PepperDash.Essentials
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) // Handles 3-series running Windows CE OS if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) // Handles 3-series running Windows CE OS
{ {
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on {1} Appliance", Global.AssemblyVersion, Global.ProcessorSeries.ToString()); string userFolder;
string nvramFolder;
bool is4series = false;
if (eCrestronSeries.Series4 == (Global.ProcessorSeries & eCrestronSeries.Series4)) // Handle 4-series
{
is4series = true;
// Set path to user/
userFolder = "user";
nvramFolder = "nvram";
}
else
{
userFolder = "User";
nvramFolder = "Nvram";
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on {1} Appliance", Global.AssemblyVersion, is4series ? "4-series" : "3-series");
// Check if User/ProgramX exists // Check if User/ProgramX exists
if (Directory.Exists(Global.ApplicationDirectoryPathPrefix + dirSeparator + "User" if (Directory.Exists(Global.ApplicationDirectoryPathPrefix + dirSeparator + userFolder
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber))) + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber)))
{ {
Debug.Console(0, @"User/program{0} directory found", InitialParametersClass.ApplicationNumber); Debug.Console(0, @"{0}/program{1} directory found", userFolder, InitialParametersClass.ApplicationNumber);
filePathPrefix = directoryPrefix + dirSeparator + "User" filePathPrefix = directoryPrefix + dirSeparator + userFolder
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
} }
// Check if Nvram/Programx exists // Check if Nvram/Programx exists
else if (Directory.Exists(directoryPrefix + dirSeparator + "Nvram" else if (Directory.Exists(directoryPrefix + dirSeparator + nvramFolder
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber))) + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber)))
{ {
Debug.Console(0, @"Nvram/program{0} directory found", InitialParametersClass.ApplicationNumber); Debug.Console(0, @"{0}/program{1} directory found", nvramFolder, InitialParametersClass.ApplicationNumber);
filePathPrefix = directoryPrefix + dirSeparator + "Nvram" filePathPrefix = directoryPrefix + dirSeparator + nvramFolder
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
} }
// If neither exists, set path to User/ProgramX // If neither exists, set path to User/ProgramX
else else
{ {
Debug.Console(0, @"No previous directory found. Using User/program{0}", InitialParametersClass.ApplicationNumber); Debug.Console(0, @"No previous directory found. Using {0}/program{1}", userFolder, InitialParametersClass.ApplicationNumber);
filePathPrefix = directoryPrefix + dirSeparator + "User" filePathPrefix = directoryPrefix + dirSeparator + userFolder
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
} }
} }
@@ -435,7 +452,7 @@ namespace PepperDash.Essentials
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms) foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
{ {
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as EssentialsRoomBase; var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom;
if (room != null) if (room != null)
{ {
// default IPID // default IPID
@@ -457,7 +474,7 @@ namespace PepperDash.Essentials
} }
} }
if (room is EssentialsHuddleSpaceRoom) if (room is IEssentialsHuddleSpaceRoom)
{ {
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
@@ -469,12 +486,12 @@ namespace PepperDash.Essentials
CreateMobileControlBridge(room); CreateMobileControlBridge(room);
} }
else if (room is EssentialsHuddleVtc1Room) else if (room is IEssentialsHuddleVtc1Room)
{ {
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion"); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)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...");
@@ -507,13 +524,22 @@ namespace PepperDash.Essentials
} }
private static void CreateMobileControlBridge(EssentialsRoomBase 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

@@ -16,7 +16,7 @@ namespace PepperDash.Essentials.Fusion
{ {
BooleanSigData CodecIsInCall; BooleanSigData CodecIsInCall;
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId, string joinMapKey) public EssentialsHuddleVtc1FusionController(IEssentialsHuddleVtc1Room room, uint ipId, string joinMapKey)
: base(room, ipId, joinMapKey) : base(room, ipId, joinMapKey)
{ {
@@ -37,7 +37,7 @@ namespace PepperDash.Essentials.Fusion
{ {
try try
{ {
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec; var codec = (Room as IEssentialsHuddleVtc1Room).VideoCodec;
if (codec == null) if (codec == null)
{ {
@@ -141,7 +141,7 @@ namespace PepperDash.Essentials.Fusion
void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e) void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e)
{ {
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec; var codec = (Room as IEssentialsHuddleVtc1Room).VideoCodec;
CodecIsInCall.InputSig.BoolValue = codec.IsInCall; CodecIsInCall.InputSig.BoolValue = codec.IsInCall;
} }
@@ -174,11 +174,11 @@ namespace PepperDash.Essentials.Fusion
// Moved to // Moved to
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.AttributeName, eSigIoMask.InputSigOnly); CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.AttributeName, eSigIoMask.InputSigOnly);
// Don't think we need to get current status of this as nothing should be alive yet. // Don't think we need to get current status of this as nothing should be alive yet.
(Room as EssentialsHuddleVtc1Room).CurrentSourceChange += Room_CurrentSourceInfoChange; (Room as IEssentialsHuddleVtc1Room).CurrentSourceChange += Room_CurrentSourceInfoChange;
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource); FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as IEssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey)); FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as IEssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey));
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler; CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
@@ -187,7 +187,7 @@ namespace PepperDash.Essentials.Fusion
protected override void SetUpSources() protected override void SetUpSources()
{ {
// Sources // Sources
var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsHuddleVtc1Room).SourceListKey); var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as IEssentialsHuddleVtc1Room).SourceListKey);
if (dict != null) if (dict != null)
{ {
// NEW PROCESS: // NEW PROCESS:
@@ -238,7 +238,7 @@ namespace PepperDash.Essentials.Fusion
else else
{ {
Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'", Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
(Room as EssentialsHuddleVtc1Room).SourceListKey, Room.Key); (Room as IEssentialsHuddleVtc1Room).SourceListKey, Room.Key);
} }
} }
@@ -259,7 +259,7 @@ namespace PepperDash.Essentials.Fusion
display.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded); display.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
} }
var defaultDisplay = (Room as EssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase; var defaultDisplay = (Room as IEssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase;
if (defaultDisplay == null) if (defaultDisplay == null)
{ {
Debug.Console(1, this, "Cannot link null display to Fusion because default display is null"); Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
@@ -332,7 +332,7 @@ namespace PepperDash.Essentials.Fusion
string displayName = string.Format("Display {0} - ", displayIndex); string displayName = string.Format("Display {0} - ", displayIndex);
if (display == (Room as EssentialsHuddleVtc1Room).DefaultDisplay) if (display == (Room as IEssentialsHuddleVtc1Room).DefaultDisplay)
{ {
// Power on // Power on
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig); var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
@@ -351,7 +351,7 @@ namespace PepperDash.Essentials.Fusion
// Current Source // Current Source
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig); var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b => { if (!b) (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey); }); ; defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b => { if (!b) (Room as IEssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey); }); ;
} }
} }
} }

View File

@@ -149,6 +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\IEssentialsHuddleSpaceRoom.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

@@ -47,7 +47,7 @@ namespace PepperDash.Essentials.Room.Config
/// Gets and operating, standalone emergegncy object that can be plugged into a room. /// Gets and operating, standalone emergegncy object that can be plugged into a room.
/// Returns null if there is no emergency defined /// Returns null if there is no emergency defined
/// </summary> /// </summary>
public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, EssentialsRoomBase room) public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, IEssentialsRoom room)
{ {
// This emergency // This emergency
var emergency = props.Emergency; var emergency = props.Emergency;
@@ -96,7 +96,7 @@ namespace PepperDash.Essentials.Room.Config
if (behaviour == "trackroomstate") if (behaviour == "trackroomstate")
{ {
// Tie LED enable to room power state // Tie LED enable to room power state
var essRoom = room as EssentialsRoomBase; var essRoom = room as IEssentialsRoom;
essRoom.OnFeedback.OutputChange += (o, a) => essRoom.OnFeedback.OutputChange += (o, a) =>
{ {
if (essRoom.OnFeedback.BoolValue) if (essRoom.OnFeedback.BoolValue)

View File

@@ -17,11 +17,11 @@ namespace PepperDash.Essentials.Room
public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase
{ {
EssentialsRoomBase Room; IEssentialsRoom Room;
string Behavior; string Behavior;
bool TriggerOnClose; bool TriggerOnClose;
public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, EssentialsRoomBase room) : public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, IEssentialsRoom room) :
base(key) base(key)
{ {
Room = room; Room = room;

View File

@@ -645,9 +645,9 @@ namespace PepperDash.Essentials
public static void AllRoomsOff() public static void AllRoomsOff()
{ {
var allRooms = DeviceManager.AllDevices.Where(d => var allRooms = DeviceManager.AllDevices.Where(d =>
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions); d is IEssentialsHuddleSpaceRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms) foreach (var room in allRooms)
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff", (room as EssentialsHuddleSpaceRoom).SourceListKey); (room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff", (room as IEssentialsHuddleSpaceRoom).SourceListKey);
} }
#region IPrivacy Members #region IPrivacy Members

View File

@@ -13,7 +13,7 @@ using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials namespace PepperDash.Essentials
{ {
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasCurrentVolumeControls, IHasDefaultDisplay public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IEssentialsHuddleSpaceRoom
{ {
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange; public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSourceChange; public event SourceInfoChangeHandler CurrentSourceChange;

View File

@@ -17,8 +17,7 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials namespace PepperDash.Essentials
{ {
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange, public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IEssentialsHuddleVtc1Room
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback
{ {
private bool _codecExternalSourceChange; private bool _codecExternalSourceChange;
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange; public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
@@ -455,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(() => { }));
} }
} }
@@ -472,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>
@@ -734,9 +738,9 @@ namespace PepperDash.Essentials
public static void AllRoomsOff() public static void AllRoomsOff()
{ {
var allRooms = DeviceManager.AllDevices.Where(d => var allRooms = DeviceManager.AllDevices.Where(d =>
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions); d is IEssentialsRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms) foreach (var room in allRooms)
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff"); (room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
} }

View File

@@ -107,14 +107,18 @@ namespace PepperDash.Essentials
private void TunerPresetsOnPresetRecalled(ISetTopBoxNumericKeypad device, string channel) private void TunerPresetsOnPresetRecalled(ISetTopBoxNumericKeypad device, string channel)
{ {
//Debug.Console(2, this, "TunerPresetsOnPresetRecalled");
if (!_currentPresets.ContainsKey(device.Key)) if (!_currentPresets.ContainsKey(device.Key))
{ {
return; return;
} }
//Debug.Console(2, this, "Tuner Key: {0} Channel: {1}", device.Key, channel);
_currentPresets[device.Key] = channel; _currentPresets[device.Key] = channel;
if (!CurrentPresetsFeedbacks.ContainsKey(device.Key)) if (CurrentPresetsFeedbacks.ContainsKey(device.Key))
{ {
CurrentPresetsFeedbacks[device.Key].FireUpdate(); CurrentPresetsFeedbacks[device.Key].FireUpdate();
} }

View File

@@ -0,0 +1,48 @@
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, IRunDefaultPresentRoute, IHasDefaultDisplay
{
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; }
IBasicVolumeControls CurrentVolumeControls { get; }
event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
}
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange,
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback
{
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
void RunRouteAction(string routeKey);
IHasScheduleAwareness ScheduleSource { get; }
BoolFeedback InCallFeedback { get; }
BoolFeedback PrivacyModeIsOnFeedback { get; }
string DefaultCodecRouteString { get; }
}
}

View File

@@ -79,6 +79,16 @@ namespace PepperDash.Essentials
Panel = new Tsw1052(id, Global.ControlSystem); Panel = new Tsw1052(id, Global.ControlSystem);
else if (type == "tsw1060") else if (type == "tsw1060")
Panel = new Tsw1060(id, Global.ControlSystem); Panel = new Tsw1060(id, Global.ControlSystem);
else if (type == "tsw570")
Panel = new Tsw570(id, Global.ControlSystem);
else if (type == "tsw770")
Panel = new Tsw770(id, Global.ControlSystem);
else if (type == "ts770")
Panel = new Ts770(id, Global.ControlSystem);
else if (type == "tsw1070")
Panel = new Tsw1070(id, Global.ControlSystem);
else if (type == "ts1070")
Panel = new Ts1070(id, Global.ControlSystem);
else else
{ {
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type);
@@ -203,7 +213,7 @@ namespace PepperDash.Essentials
{ {
public EssentialsTouchpanelControllerFactory() public EssentialsTouchpanelControllerFactory()
{ {
TypeNames = new List<string>() { "tsw550", "tsw750", "tsw1050", "tsw560", "tsw760", "tsw1060", "xpanel" }; TypeNames = new List<string>() { "tsw550", "tsw750", "tsw1050", "tsw560", "tsw760", "tsw1060", "tsw570", "tsw770", "ts770", "tsw1070", "ts1070", "xpanel" };
} }
public override EssentialsDevice BuildDevice(DeviceConfig dc) public override EssentialsDevice BuildDevice(DeviceConfig dc)
@@ -222,7 +232,7 @@ namespace PepperDash.Essentials
// spin up different room drivers depending on room type // spin up different room drivers depending on room type
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey); var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
if (room is EssentialsHuddleSpaceRoom) if (room is IEssentialsHuddleSpaceRoom)
{ {
// Screen Saver Driver // Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props); mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props);
@@ -236,7 +246,7 @@ namespace PepperDash.Essentials
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props); var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
avDriver.DefaultRoomKey = props.DefaultRoomKey; avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver; mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom; avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom;
// Environment Driver // Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
@@ -270,7 +280,7 @@ namespace PepperDash.Essentials
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress); tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
} }
} }
else if (room is EssentialsHuddleVtc1Room) else if (room is IEssentialsHuddleVtc1Room)
{ {
Debug.Console(0, panelController, "Adding huddle space VTC AV driver"); Debug.Console(0, panelController, "Adding huddle space VTC AV driver");
@@ -284,11 +294,11 @@ namespace PepperDash.Essentials
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props); var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props);
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(panelController.Panel, avDriver, var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(panelController.Panel, avDriver,
(room as EssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver); (room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver);
avDriver.SetVideoCodecDriver(codecDriver); avDriver.SetVideoCodecDriver(codecDriver);
avDriver.DefaultRoomKey = props.DefaultRoomKey; avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver; mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as EssentialsHuddleVtc1Room; avDriver.CurrentRoom = room as IEssentialsHuddleVtc1Room;
// Environment Driver // Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0) if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)

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>
@@ -764,6 +773,10 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public const uint NextMeetingModalVisible = 15049; public const uint NextMeetingModalVisible = 15049;
/// <summary> /// <summary>
/// 15050
/// </summary>
public const uint NextMeetingNotificationRibbonVisible = 15050;
/// <summary>
/// 15051 /// 15051
/// </summary> /// </summary>
public const uint Display1SelectPressAndFb = 15051; public const uint Display1SelectPressAndFb = 15051;

View File

@@ -146,18 +146,18 @@
// } // }
// void CurrentRoom_CurrentSourceInfoChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) // void CurrentRoom_CurrentSourceInfoChange(IEssentialsRoom room, SourceListItem info, ChangeType type)
// { // {
// } // }
// void CurrentRoom_CurrentDisplay1SourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) // void CurrentRoom_CurrentDisplay1SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type)
// { // {
// TriList.StringInput[UIStringJoin.Display1SourceLabel].StringValue = PendingSource.PreferredName; // TriList.StringInput[UIStringJoin.Display1SourceLabel].StringValue = PendingSource.PreferredName;
// } // }
// void CurrentRoom_CurrentDisplay2SourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) // void CurrentRoom_CurrentDisplay2SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type)
// { // {
// TriList.StringInput[UIStringJoin.Display2SourceLabel].StringValue = PendingSource.PreferredName; // TriList.StringInput[UIStringJoin.Display2SourceLabel].StringValue = PendingSource.PreferredName;
// } // }

View File

@@ -52,7 +52,7 @@ namespace PepperDash.Essentials
CaretInterlock = new JoinedSigInterlock(TriList); CaretInterlock = new JoinedSigInterlock(TriList);
} }
void SetUpGear(IAVDriver avDriver, EssentialsRoomBase currentRoom) void SetUpGear(IAVDriver avDriver, IEssentialsRoom currentRoom)
{ {
// Gear // Gear
TriList.SetString(UIStringJoin.HeaderButtonIcon5, "Gear"); TriList.SetString(UIStringJoin.HeaderButtonIcon5, "Gear");
@@ -105,7 +105,7 @@ namespace PepperDash.Essentials
{ {
string message = null; string message = null;
var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey) var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey)
as EssentialsHuddleSpaceRoom; as IEssentialsHuddleSpaceRoom;
if (room != null) if (room != null)
message = room.PropertiesConfig.HelpMessage; message = room.PropertiesConfig.HelpMessage;
else else
@@ -207,6 +207,7 @@ namespace PepperDash.Essentials
//TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 1); //TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 1);
// Set the call status text // Set the call status text
Debug.Console(1, "Active Call Count: {0}", codec.ActiveCalls.Count);
if (codec.ActiveCalls.Count > 0) if (codec.ActiveCalls.Count > 0)
{ {
if (codec.ActiveCalls.Count == 1) if (codec.ActiveCalls.Count == 1)
@@ -221,7 +222,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// Sets up Header Buttons for the EssentialsHuddleVtc1Room type /// Sets up Header Buttons for the EssentialsHuddleVtc1Room type
/// </summary> /// </summary>
public void SetupHeaderButtons(EssentialsHuddleVtc1PanelAvFunctionsDriver avDriver, EssentialsHuddleVtc1Room currentRoom) public void SetupHeaderButtons(EssentialsHuddleVtc1PanelAvFunctionsDriver avDriver, IEssentialsHuddleVtc1Room currentRoom)
{ {
HeaderButtonsAreSetUp = false; HeaderButtonsAreSetUp = false;
@@ -283,7 +284,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// Sets up Header Buttons for the EssentialsHuddleSpaceRoom type /// Sets up Header Buttons for the EssentialsHuddleSpaceRoom type
/// </summary> /// </summary>
public void SetupHeaderButtons(EssentialsHuddlePanelAvFunctionsDriver avDriver, EssentialsHuddleSpaceRoom currentRoom) public void SetupHeaderButtons(EssentialsHuddlePanelAvFunctionsDriver avDriver, IEssentialsHuddleSpaceRoom currentRoom)
{ {
HeaderButtonsAreSetUp = false; HeaderButtonsAreSetUp = false;

View File

@@ -983,7 +983,7 @@
// /// <summary> // /// <summary>
// /// Handles source change // /// Handles source change
// /// </summary> // /// </summary>
// void _CurrentRoom_SourceInfoChange(EssentialsRoomBase room, // void _CurrentRoom_SourceInfoChange(IEssentialsRoom room,
// SourceListItem info, ChangeType change) // SourceListItem info, ChangeType change)
// { // {
// if (change == ChangeType.WillChange) // if (change == ChangeType.WillChange)
@@ -995,7 +995,7 @@
// /// <summary> // /// <summary>
// /// // ///
// /// </summary> // /// </summary>
// void _CurrentRoom_CurrentDisplay1SourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) // void _CurrentRoom_CurrentDisplay1SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type)
// { // {
// if (type == ChangeType.DidChange) // if (type == ChangeType.DidChange)
// { // {
@@ -1021,7 +1021,7 @@
// /// <summary> // /// <summary>
// /// // ///
// /// </summary> // /// </summary>
// void _CurrentRoom_CurrentDisplay2SourceChange(EssentialsRoomBase room, SourceListItem info, ChangeType type) // void _CurrentRoom_CurrentDisplay2SourceChange(IEssentialsRoom room, SourceListItem info, ChangeType type)
// { // {
// if (type == ChangeType.DidChange) // if (type == ChangeType.DidChange)
// { // {

View File

@@ -78,7 +78,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public EssentialsHuddleSpaceRoom CurrentRoom public IEssentialsHuddleSpaceRoom CurrentRoom
{ {
get { return _CurrentRoom; } get { return _CurrentRoom; }
set set
@@ -86,7 +86,7 @@ namespace PepperDash.Essentials
SetCurrentRoom(value); SetCurrentRoom(value);
} }
} }
EssentialsHuddleSpaceRoom _CurrentRoom; IEssentialsHuddleSpaceRoom _CurrentRoom;
/// <summary> /// <summary>
/// ///
@@ -498,7 +498,7 @@ namespace PepperDash.Essentials
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = true; TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = 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)
CurrentRoom.RunDefaultPresentRoute(); (CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute();
} }
@@ -583,7 +583,7 @@ namespace PepperDash.Essentials
void UiSelectSource(string key) void UiSelectSource(string key)
{ {
// Run the route and when it calls back, show the source // Run the route and when it calls back, show the source
CurrentRoom.RunRouteAction(key, new Action(() => { })); CurrentRoom.RunRouteAction(key);
} }
/// <summary> /// <summary>
@@ -745,7 +745,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// Helper for property setter. Sets the panel to the given room, latching up all functionality /// Helper for property setter. Sets the panel to the given room, latching up all functionality
/// </summary> /// </summary>
public void RefreshCurrentRoom(EssentialsHuddleSpaceRoom room) public void RefreshCurrentRoom(IEssentialsHuddleSpaceRoom room)
{ {
if (_CurrentRoom != null) if (_CurrentRoom != null)
{ {
@@ -836,7 +836,7 @@ namespace PepperDash.Essentials
} }
} }
void SetCurrentRoom(EssentialsHuddleSpaceRoom room) void SetCurrentRoom(IEssentialsHuddleSpaceRoom room)
{ {
if (_CurrentRoom == room) return; if (_CurrentRoom == room) return;
// Disconnect current (probably never called) // Disconnect current (probably never called)
@@ -871,7 +871,7 @@ namespace PepperDash.Essentials
UpdateMCJoins(_CurrentRoom); UpdateMCJoins(_CurrentRoom);
} }
void UpdateMCJoins(EssentialsHuddleSpaceRoom room) void UpdateMCJoins(IEssentialsHuddleSpaceRoom room)
{ {
TriList.SetString(UIStringJoin.RoomMcUrl, room.MobileControlRoomBridge.McServerUrl); TriList.SetString(UIStringJoin.RoomMcUrl, room.MobileControlRoomBridge.McServerUrl);
TriList.SetString(UIStringJoin.RoomMcQrCodeUrl, room.MobileControlRoomBridge.QrCodeUrl); TriList.SetString(UIStringJoin.RoomMcQrCodeUrl, room.MobileControlRoomBridge.QrCodeUrl);

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

@@ -50,7 +50,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public EssentialsHuddleVtc1Room CurrentRoom public IEssentialsHuddleVtc1Room CurrentRoom
{ {
get { return _CurrentRoom; } get { return _CurrentRoom; }
set set
@@ -58,7 +58,7 @@ namespace PepperDash.Essentials
SetCurrentRoom(value); SetCurrentRoom(value);
} }
} }
EssentialsHuddleVtc1Room _CurrentRoom; IEssentialsHuddleVtc1Room _CurrentRoom;
/// <summary> /// <summary>
/// For hitting feedbacks /// For hitting feedbacks
@@ -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,22 @@ 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);
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 +652,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,16 +671,13 @@ 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 (!CurrentRoom.OnFeedback.BoolValue)
{ {
// If there's no default, show UI elements // If there's no default, show UI elements
if (!CurrentRoom.RunDefaultPresentRoute()) if (!(CurrentRoom as IRunDefaultPresentRoute).RunDefaultPresentRoute())
TriList.SetBool(UIBoolJoin.SelectASourceVisible, true); TriList.SetBool(UIBoolJoin.SelectASourceVisible, true);
} }
} }
@@ -665,7 +690,6 @@ namespace PepperDash.Essentials
} }
CurrentMode = UiDisplayMode.Presentation; CurrentMode = UiDisplayMode.Presentation;
SetupSourceList(); SetupSourceList();
SetActivityFooterFeedbacks();
} }
/// <summary> /// <summary>
@@ -707,6 +731,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);
@@ -743,7 +769,7 @@ namespace PepperDash.Essentials
void UiSelectSource(string key) void UiSelectSource(string key)
{ {
// Run the route and when it calls back, show the source // Run the route and when it calls back, show the source
CurrentRoom.RunRouteAction(key, new Action(() => { })); CurrentRoom.RunRouteAction(key);
} }
/// <summary> /// <summary>
@@ -894,7 +920,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// Helper for property setter. Sets the panel to the given room, latching up all functionality /// Helper for property setter. Sets the panel to the given room, latching up all functionality
/// </summary> /// </summary>
void RefreshCurrentRoom(EssentialsHuddleVtc1Room room) void RefreshCurrentRoom(IEssentialsHuddleVtc1Room room)
{ {
if (_CurrentRoom != null) if (_CurrentRoom != null)
@@ -969,7 +995,7 @@ namespace PepperDash.Essentials
} }
} }
void SetCurrentRoom(EssentialsHuddleVtc1Room room) void SetCurrentRoom(IEssentialsHuddleVtc1Room room)
{ {
if (_CurrentRoom == room) return; if (_CurrentRoom == room) return;
// Disconnect current (probably never called) // Disconnect current (probably never called)
@@ -1004,7 +1030,7 @@ namespace PepperDash.Essentials
UpdateMCJoins(_CurrentRoom); UpdateMCJoins(_CurrentRoom);
} }
void UpdateMCJoins(EssentialsHuddleVtc1Room room) void UpdateMCJoins(IEssentialsHuddleVtc1Room room)
{ {
TriList.SetString(UIStringJoin.RoomMcUrl, room.MobileControlRoomBridge.McServerUrl); TriList.SetString(UIStringJoin.RoomMcUrl, room.MobileControlRoomBridge.McServerUrl);
TriList.SetString(UIStringJoin.RoomMcQrCodeUrl, room.MobileControlRoomBridge.QrCodeUrl); TriList.SetString(UIStringJoin.RoomMcQrCodeUrl, room.MobileControlRoomBridge.QrCodeUrl);
@@ -1035,7 +1061,7 @@ namespace PepperDash.Essentials
if (CurrentRoom.CurrentSourceInfo != null && CurrentRoom.CurrentSourceInfo.DisableCodecSharing) if (CurrentRoom.CurrentSourceInfo != null && CurrentRoom.CurrentSourceInfo.DisableCodecSharing)
{ {
Debug.Console(1, CurrentRoom, "Transitioning to in-call, cancelling non-sharable source"); Debug.Console(1, CurrentRoom, "Transitioning to in-call, cancelling non-sharable source");
CurrentRoom.RunRouteAction("codecOsd", CurrentRoom.SourceListKey); CurrentRoom.RunRouteAction("codecOsd");
} }
} }
@@ -1218,9 +1244,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;
} }
@@ -1443,7 +1468,7 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public interface IAVWithVCDriver : IAVDriver public interface IAVWithVCDriver : IAVDriver
{ {
EssentialsHuddleVtc1Room CurrentRoom { get; } IEssentialsHuddleVtc1Room CurrentRoom { get; }
PepperDash.Essentials.Core.Touchpanels.Keyboards.HabaneroKeyboardController Keyboard { get; } PepperDash.Essentials.Core.Touchpanels.Keyboards.HabaneroKeyboardController Keyboard { get; }
/// <summary> /// <summary>

View File

@@ -38,7 +38,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// Sets feedback for the given room /// Sets feedback for the given room
/// </summary> /// </summary>
public void SetFeedbackForRoom(EssentialsHuddleSpaceRoom room) public void SetFeedbackForRoom(IEssentialsHuddleSpaceRoom room)
{ {
var itemToSet = Items.FirstOrDefault(i => i.Room == room); var itemToSet = Items.FirstOrDefault(i => i.Room == room);
if (itemToSet != null) if (itemToSet != null)
@@ -48,11 +48,11 @@ namespace PepperDash.Essentials
public class SmartObjectRoomsListItem public class SmartObjectRoomsListItem
{ {
public EssentialsHuddleSpaceRoom Room { get; private set; } public IEssentialsHuddleSpaceRoom Room { get; private set; }
SmartObjectRoomsList Parent; SmartObjectRoomsList Parent;
public uint Index { get; private set; } public uint Index { get; private set; }
public SmartObjectRoomsListItem(EssentialsHuddleSpaceRoom room, uint index, SmartObjectRoomsList parent, public SmartObjectRoomsListItem(IEssentialsHuddleSpaceRoom room, uint index, SmartObjectRoomsList parent,
Action<bool> buttonAction) Action<bool> buttonAction)
{ {
Room = room; Room = room;

View File

@@ -12,5 +12,5 @@ namespace PepperDash.Essentials
///// <summary> ///// <summary>
///// The handler type for a Room's SourceInfoChange ///// The handler type for a Room's SourceInfoChange
///// </summary> ///// </summary>
//public delegate void SourceInfoChangeHandler(EssentialsRoomBase room, SourceListItem info, ChangeType type); //public delegate void SourceInfoChangeHandler(IEssentialsRoom room, SourceListItem info, ChangeType type);
} }

View File

@@ -142,7 +142,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);
@@ -354,7 +357,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 +521,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 +567,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 +782,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 +854,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 +1041,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 +1063,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 +1083,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 +1103,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 +1135,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 +1172,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 +1225,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 +1270,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 +1283,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 +1291,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>

View File

@@ -385,7 +385,7 @@ namespace PepperDash.Essentials.Core.Bridges
{ {
public EiscApiAdvancedFactory() public EiscApiAdvancedFactory()
{ {
TypeNames = new List<string> { "eiscapiadv", "eiscapiadvanced", "vceiscapiadv", "vceiscapiadvanced" }; TypeNames = new List<string> { "eiscapiadv", "eiscapiadvanced", "eiscapiadvancedserver", "eiscapiadvancedclient", "vceiscapiadv", "vceiscapiadvanced" };
} }
public override EssentialsDevice BuildDevice(DeviceConfig dc) public override EssentialsDevice BuildDevice(DeviceConfig dc)
@@ -403,6 +403,16 @@ namespace PepperDash.Essentials.Core.Bridges
controlProperties.TcpSshProperties.Address, Global.ControlSystem); controlProperties.TcpSshProperties.Address, Global.ControlSystem);
return new EiscApiAdvanced(dc, eisc); return new EiscApiAdvanced(dc, eisc);
} }
case "eiscapiadvancedserver":
{
var eisc = new EISCServer(controlProperties.IpIdInt, Global.ControlSystem);
return new EiscApiAdvanced(dc, eisc);
}
case "eiscapiadvancedclient":
{
var eisc = new EISCClient(controlProperties.IpIdInt, controlProperties.TcpSshProperties.Address, Global.ControlSystem);
return new EiscApiAdvanced(dc, eisc);
}
case "vceiscapiadv": case "vceiscapiadv":
case "vceiscapiadvanced": case "vceiscapiadvanced":
{ {

View File

@@ -54,11 +54,11 @@ namespace PepperDash.Essentials.Core.Config
{ {
bool success = false; bool success = false;
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(config.Key)); var deviceConfigIndex = ConfigReader.ConfigObject.Devices.FindIndex(d => d.Key.Equals(config.Key));
if (deviceConfig != null) if (deviceConfigIndex >= 0)
{ {
deviceConfig = config; ConfigReader.ConfigObject.Devices[deviceConfigIndex] = config;
Debug.Console(1, "Updated config of device: '{0}'", config.Key); Debug.Console(1, "Updated config of device: '{0}'", config.Key);
@@ -74,13 +74,13 @@ namespace PepperDash.Essentials.Core.Config
{ {
bool success = false; bool success = false;
var deviceConfig = ConfigReader.ConfigObject.Rooms.FirstOrDefault(d => d.Key.Equals(config.Key)); var roomConfigIndex = ConfigReader.ConfigObject.Rooms.FindIndex(d => d.Key.Equals(config.Key));
if (deviceConfig != null) if (roomConfigIndex >= 0)
{ {
deviceConfig = config; ConfigReader.ConfigObject.Rooms[roomConfigIndex] = config;
Debug.Console(1, "Updated config of device: '{0}'", config.Key); Debug.Console(1, "Updated room of device: '{0}'", config.Key);
success = true; success = true;
} }

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.GeneralIO;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO
{
public class C2NIoController:CrestronGenericBaseDevice, IComPorts, IIROutputPorts, IRelayPorts
{
private C2nIo _device;
public C2NIoController(string key, Func<DeviceConfig, C2nIo> preActivationFunc, DeviceConfig config):base(key, config.Name)
{
AddPreActivationAction(() =>
{
_device = preActivationFunc(config);
RegisterCrestronGenericBase(_device);
});
}
#region Implementation of IComPorts
public CrestronCollection<ComPort> ComPorts
{
get { return _device.ComPorts; }
}
public int NumberOfComPorts
{
get { return _device.NumberOfComPorts; }
}
#endregion
#region Implementation of IIROutputPorts
public CrestronCollection<IROutputPort> IROutputPorts
{
get { return _device.IROutputPorts; }
}
public int NumberOfIROutputPorts
{
get { return _device.NumberOfIROutputPorts; }
}
#endregion
#region Implementation of IRelayPorts
public CrestronCollection<Relay> RelayPorts
{
get { return _device.RelayPorts; }
}
public int NumberOfRelayPorts
{
get { return _device.NumberOfRelayPorts; }
}
#endregion
}
public class C2NIoControllerFactory : EssentialsDeviceFactory<C2nRthsController>
{
public C2NIoControllerFactory()
{
TypeNames = new List<string>() { "c2nio" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new C2N-IO Device");
return new C2NIoController(dc.Key, GetC2NIoDevice, dc);
}
static C2nIo GetC2NIoDevice(DeviceConfig dc)
{
var control = CommFactory.GetControlPropertiesConfig(dc);
var cresnetId = control.CresnetIdInt;
var branchId = control.ControlPortNumber;
var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey;
if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase))
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new C2nIo", parentKey);
return new C2nIo(cresnetId, Global.ControlSystem);
}
var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches;
if (cresnetBridge != null)
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new C2nIo", parentKey);
return new C2nIo(cresnetId, cresnetBridge.CresnetBranches[branchId]);
}
Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey);
return null;
}
}
}

View File

@@ -13,6 +13,14 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
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

@@ -19,10 +19,25 @@ namespace PepperDash.Essentials.Core
/// </summary> /// </summary>
/// <param name="json"></param> /// <param name="json"></param>
public static void DoDeviceActionWithJson(string json) public static void DoDeviceActionWithJson(string json)
{
if (String.IsNullOrEmpty(json))
{
CrestronConsole.ConsoleCommandResponse(
"Please provide a JSON object matching the format {\"deviceKey\":\"myDevice\", \"methodName\":\"someMethod\", \"params\": [\"param1\", true]}.\r\nIf the method has no parameters, the \"params\" object may be omitted.");
return;
}
try
{ {
var action = JsonConvert.DeserializeObject<DeviceActionWrapper>(json); var action = JsonConvert.DeserializeObject<DeviceActionWrapper>(json);
DoDeviceAction(action); DoDeviceAction(action);
} }
catch (Exception ex)
{
CrestronConsole.ConsoleCommandResponse("Incorrect format for JSON. Please check that the format matches {\"deviceKey\":\"myDevice\", \"methodName\":\"someMethod\", \"params\": [\"param1\", true]}");
}
}
/// <summary> /// <summary>
@@ -34,28 +49,62 @@ namespace PepperDash.Essentials.Core
var key = action.DeviceKey; var key = action.DeviceKey;
var obj = FindObjectOnPath(key); var obj = FindObjectOnPath(key);
if (obj == null) if (obj == null)
{
CrestronConsole.ConsoleCommandResponse("Unable to find object at path {0}", key);
return; return;
}
if (action.Params == null)
{
//no params, so setting action.Params to empty array
action.Params = new object[0];
}
CType t = obj.GetType(); CType t = obj.GetType();
var method = t.GetMethod(action.MethodName); try
{
var methods = t.GetMethods().Where(m => m.Name == action.MethodName).ToList();
var method = methods.Count == 1 ? methods[0] : methods.FirstOrDefault(m => m.GetParameters().Length == action.Params.Length);
if (method == null) if (method == null)
{ {
Debug.Console(0, "Method '{0}' not found", action.MethodName); CrestronConsole.ConsoleCommandResponse(
"Unable to find method with name {0} and that matches parameters {1}", action.MethodName,
action.Params);
return; return;
} }
var mParams = method.GetParameters(); var mParams = method.GetParameters();
// Add empty params if not provided
if (action.Params == null) action.Params = new object[0]; var convertedParams = mParams
if (mParams.Length > action.Params.Length) .Select((p, i) => ConvertType(action.Params[i], p.ParameterType))
{
Debug.Console(0, "Method '{0}' requires {1} params", action.MethodName, mParams.Length);
return;
}
object[] convertedParams = mParams
.Select((p, i) => Convert.ChangeType(action.Params[i], p.ParameterType,
System.Globalization.CultureInfo.InvariantCulture))
.ToArray(); .ToArray();
object ret = method.Invoke(obj, convertedParams); method.Invoke(obj, convertedParams);
CrestronConsole.ConsoleCommandResponse("Method {0} successfully called on device {1}", method.Name,
action.DeviceKey);
}
catch (Exception ex)
{
CrestronConsole.ConsoleCommandResponse("Unable to call method with name {0}. {1}", action.MethodName,
ex.Message);}
}
private static object ConvertType(object value, Type conversionType)
{
if (!conversionType.IsEnum)
{
return Convert.ChangeType(value, conversionType, System.Globalization.CultureInfo.InvariantCulture);
}
var stringValue = Convert.ToString(value);
if (String.IsNullOrEmpty(stringValue))
{
throw new InvalidCastException(
String.Format("{0} cannot be converted to a string prior to conversion to enum"));
}
return Enum.Parse(conversionType, stringValue, true);
} }
/// <summary> /// <summary>
@@ -242,6 +291,8 @@ namespace PepperDash.Essentials.Core
//var props = t.GetProperties().Select(p => new PropertyNameType(p, obj)); //var props = t.GetProperties().Select(p => new PropertyNameType(p, obj));
//return JsonConvert.SerializeObject(props, Formatting.Indented); //return JsonConvert.SerializeObject(props, Formatting.Indented);
} }
} }
public class DeviceActionWrapper public class DeviceActionWrapper

View File

@@ -435,7 +435,7 @@ namespace PepperDash.Essentials.Core
var min = Convert.ToUInt32(timeout); var min = Convert.ToUInt32(timeout);
device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min); device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min);
Debug.Console(0, "Device: '{0}' debug level set to {1) for {2} minutes", deviceKey, debugSetting, min); Debug.Console(0, "Device: '{0}' debug level set to {1} for {2} minutes", deviceKey, debugSetting, min);
} }
catch (Exception e) catch (Exception e)

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.Devices
{
public interface IReconfigurableDevice
{
event EventHandler<EventArgs> ConfigChanged;
DeviceConfig Config { get; }
void SetConfig(DeviceConfig config);
}
}

View File

@@ -7,13 +7,15 @@ using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Config;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace PepperDash.Essentials.Core.Devices namespace PepperDash.Essentials.Core.Devices
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public abstract class ReconfigurableDevice : EssentialsDevice public abstract class ReconfigurableDevice : EssentialsDevice, IReconfigurableDevice
{ {
public event EventHandler<EventArgs> ConfigChanged; public event EventHandler<EventArgs> ConfigChanged;
@@ -52,6 +54,8 @@ namespace PepperDash.Essentials.Core.Devices
Name = config.Name; Name = config.Name;
} }
/// <summary> /// <summary>
/// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc) /// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc)
/// </summary> /// </summary>

View File

@@ -59,6 +59,9 @@ namespace PepperDash.Essentials.Core
VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; }); VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; });
MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted); MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted);
WarmupTime = 10000;
CooldownTime = 5000;
} }
public override void PowerOn() public override void PowerOn()

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

@@ -23,7 +23,7 @@ namespace PepperDash.Essentials.Core
protected bool ComputedValue; protected bool ComputedValue;
public BoolFeedbackLogic() protected BoolFeedbackLogic()
{ {
Output = new BoolFeedback(() => ComputedValue); Output = new BoolFeedback(() => ComputedValue);
} }
@@ -40,11 +40,8 @@ namespace PepperDash.Essentials.Core
public void AddOutputsIn(List<BoolFeedback> outputs) public void AddOutputsIn(List<BoolFeedback> outputs)
{ {
foreach (var o in outputs) foreach (var o in outputs.Where(o => !OutputsIn.Contains(o)))
{ {
// skip existing
if (OutputsIn.Contains(o)) continue;
OutputsIn.Add(o); OutputsIn.Add(o);
o.OutputChange += AnyInput_OutputChange; o.OutputChange += AnyInput_OutputChange;
} }
@@ -54,7 +51,7 @@ namespace PepperDash.Essentials.Core
public void RemoveOutputIn(BoolFeedback output) public void RemoveOutputIn(BoolFeedback output)
{ {
// Don't double up outputs // Don't double up outputs
if (OutputsIn.Contains(output)) return; if (!OutputsIn.Contains(output)) return;
OutputsIn.Remove(output); OutputsIn.Remove(output);
output.OutputChange -= AnyInput_OutputChange; output.OutputChange -= AnyInput_OutputChange;
@@ -71,6 +68,12 @@ namespace PepperDash.Essentials.Core
Evaluate(); Evaluate();
} }
public void ClearOutputs()
{
OutputsIn.Clear();
Evaluate();
}
void AnyInput_OutputChange(object sender, EventArgs e) void AnyInput_OutputChange(object sender, EventArgs e)
{ {
Evaluate(); Evaluate();
@@ -85,13 +88,14 @@ namespace PepperDash.Essentials.Core
{ {
var prevValue = ComputedValue; var prevValue = ComputedValue;
var newValue = OutputsIn.All(o => o.BoolValue); var newValue = OutputsIn.All(o => o.BoolValue);
if (newValue != prevValue) if (newValue == prevValue)
{ {
return;
}
ComputedValue = newValue; ComputedValue = newValue;
Output.FireUpdate(); Output.FireUpdate();
} }
} }
}
public class BoolFeedbackOr : BoolFeedbackLogic public class BoolFeedbackOr : BoolFeedbackLogic
{ {
@@ -99,33 +103,35 @@ namespace PepperDash.Essentials.Core
{ {
var prevValue = ComputedValue; var prevValue = ComputedValue;
var newValue = OutputsIn.Any(o => o.BoolValue); var newValue = OutputsIn.Any(o => o.BoolValue);
if (newValue != prevValue) if (newValue == prevValue)
{ {
return;
}
ComputedValue = newValue; ComputedValue = newValue;
Output.FireUpdate(); Output.FireUpdate();
} }
} }
}
public class BoolFeedbackLinq : BoolFeedbackLogic public class BoolFeedbackLinq : BoolFeedbackLogic
{ {
Func<IEnumerable<BoolFeedback>, bool> Predicate; readonly Func<IEnumerable<BoolFeedback>, bool> _predicate;
public BoolFeedbackLinq(Func<IEnumerable<BoolFeedback>, bool> predicate) public BoolFeedbackLinq(Func<IEnumerable<BoolFeedback>, bool> predicate)
: base() : base()
{ {
Predicate = predicate; _predicate = predicate;
} }
protected override void Evaluate() protected override void Evaluate()
{ {
var prevValue = ComputedValue; var prevValue = ComputedValue;
var newValue = Predicate(OutputsIn); var newValue = _predicate(OutputsIn);
if (newValue != prevValue) if (newValue == prevValue)
{ {
return;
}
ComputedValue = newValue; ComputedValue = newValue;
Output.FireUpdate(); Output.FireUpdate();
} }
} }
} }
}

View File

@@ -33,7 +33,7 @@ namespace PepperDash.Essentials.Core.Fusion
protected FusionRoom FusionRoom; protected FusionRoom FusionRoom;
protected Dictionary<int, FusionAsset> FusionStaticAssets; protected Dictionary<int, FusionAsset> FusionStaticAssets;
public long PushNotificationTimeout = 5000; public long PushNotificationTimeout = 5000;
protected EssentialsRoomBase Room; protected IEssentialsRoom Room;
public long SchedulePollInterval = 300000; public long SchedulePollInterval = 300000;
private Event _currentMeeting; private Event _currentMeeting;
@@ -86,7 +86,7 @@ namespace PepperDash.Essentials.Core.Fusion
#endregion #endregion
public EssentialsHuddleSpaceFusionSystemControllerBase(EssentialsRoomBase room, uint ipId, string joinMapKey) public EssentialsHuddleSpaceFusionSystemControllerBase(IEssentialsRoom room, uint ipId, string joinMapKey)
: base(room.Key + "-fusion") : base(room.Key + "-fusion")
{ {
try try

View File

@@ -82,7 +82,7 @@ namespace PepperDash.Essentials.Core.Fusion
deviceConfig.Properties = JToken.FromObject(devProps); deviceConfig.Properties = JToken.FromObject(devProps);
} }
else if (device is EssentialsRoomBase) else if (device is IEssentialsRoom)
{ {
// Set the room name // Set the room name
if (!string.IsNullOrEmpty(roomInfo.Name)) if (!string.IsNullOrEmpty(roomInfo.Name))

View File

@@ -3,16 +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.SimplSharpPro.GeneralIO;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// Aggregates the RoomIsOccupied feedbacks of one or more IOccupancyStatusProvider objects /// Aggregates the RoomIsOccupied feedbacks of one or more IOccupancyStatusProvider objects
/// </summary> /// </summary>
public class IOccupancyStatusProviderAggregator : Device, IOccupancyStatusProvider public class IOccupancyStatusProviderAggregator : EssentialsDevice, IOccupancyStatusProvider
{ {
/// <summary> /// <summary>
/// Aggregated feedback of all linked IOccupancyStatusProvider devices /// Aggregated feedback of all linked IOccupancyStatusProvider devices
@@ -21,16 +22,51 @@ namespace PepperDash.Essentials.Core
{ {
get get
{ {
return AggregatedOccupancyStatus.Output; return _aggregatedOccupancyStatus.Output;
} }
} }
private BoolFeedbackOr AggregatedOccupancyStatus; private readonly BoolFeedbackOr _aggregatedOccupancyStatus;
public IOccupancyStatusProviderAggregator(string key, string name) public IOccupancyStatusProviderAggregator(string key, string name)
: base(key, name) : base(key, name)
{ {
AggregatedOccupancyStatus = new BoolFeedbackOr(); _aggregatedOccupancyStatus = new BoolFeedbackOr();
}
public IOccupancyStatusProviderAggregator(string key, string name, OccupancyAggregatorConfig config)
: this(key, name)
{
AddPostActivationAction(() =>
{
if (config.DeviceKeys.Count == 0)
{
return;
}
foreach (var deviceKey in config.DeviceKeys)
{
var device = DeviceManager.GetDeviceForKey(deviceKey);
if (device == null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice,
"Unable to retrieve Occupancy provider with key {0}", deviceKey);
continue;
}
var provider = device as IOccupancyStatusProvider;
if (provider == null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice,
"Device with key {0} does NOT implement IOccupancyStatusProvider. Please check configuration.");
continue;
}
AddOccupancyStatusProvider(provider);
}
});
} }
/// <summary> /// <summary>
@@ -39,7 +75,35 @@ namespace PepperDash.Essentials.Core
/// <param name="statusProvider"></param> /// <param name="statusProvider"></param>
public void AddOccupancyStatusProvider(IOccupancyStatusProvider statusProvider) public void AddOccupancyStatusProvider(IOccupancyStatusProvider statusProvider)
{ {
AggregatedOccupancyStatus.AddOutputIn(statusProvider.RoomIsOccupiedFeedback); _aggregatedOccupancyStatus.AddOutputIn(statusProvider.RoomIsOccupiedFeedback);
}
public void RemoveOccupancyStatusProvider(IOccupancyStatusProvider statusProvider)
{
_aggregatedOccupancyStatus.RemoveOutputIn(statusProvider.RoomIsOccupiedFeedback);
}
public void ClearOccupancyStatusProviders()
{
_aggregatedOccupancyStatus.ClearOutputs();
}
}
public class OccupancyAggregatorFactory : EssentialsDeviceFactory<IOccupancyStatusProviderAggregator>
{
public OccupancyAggregatorFactory()
{
TypeNames = new List<string> { "occupancyAggregator", "occAggregate" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device");
var config = dc.Properties.ToObject<OccupancyAggregatorConfig>();
return new IOccupancyStatusProviderAggregator(dc.Key, dc.Name, config);
} }
} }
} }

View File

@@ -0,0 +1,15 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
public class OccupancyAggregatorConfig
{
[JsonProperty("deviceKeys")] public List<string> DeviceKeys { get; set; }
public OccupancyAggregatorConfig()
{
DeviceKeys = new List<string>();
}
}
}

View File

@@ -162,6 +162,7 @@
<Compile Include="Config\Essentials\ConfigWriter.cs" /> <Compile Include="Config\Essentials\ConfigWriter.cs" />
<Compile Include="Config\Essentials\EssentialsConfig.cs" /> <Compile Include="Config\Essentials\EssentialsConfig.cs" />
<Compile Include="Config\SourceDevicePropertiesConfigBase.cs" /> <Compile Include="Config\SourceDevicePropertiesConfigBase.cs" />
<Compile Include="Crestron IO\C2nIo\C2nIoController.cs" />
<Compile Include="Crestron IO\C2nRts\C2nRthsController.cs" /> <Compile Include="Crestron IO\C2nRts\C2nRthsController.cs" />
<Compile Include="Crestron IO\Cards\C3CardControllerBase.cs" /> <Compile Include="Crestron IO\Cards\C3CardControllerBase.cs" />
<Compile Include="Crestron IO\Cards\C3Com3Controller.cs" /> <Compile Include="Crestron IO\Cards\C3Com3Controller.cs" />
@@ -197,6 +198,7 @@
<Compile Include="Devices\GenericIRController.cs" /> <Compile Include="Devices\GenericIRController.cs" />
<Compile Include="Devices\IDspPreset.cs" /> <Compile Include="Devices\IDspPreset.cs" />
<Compile Include="Devices\IProjectorInterfaces.cs" /> <Compile Include="Devices\IProjectorInterfaces.cs" />
<Compile Include="Devices\IReconfigurableDevice.cs" />
<Compile Include="Devices\PC\InRoomPc.cs" /> <Compile Include="Devices\PC\InRoomPc.cs" />
<Compile Include="Devices\PC\Laptop.cs" /> <Compile Include="Devices\PC\Laptop.cs" />
<Compile Include="Devices\ReconfigurableDevice.cs" /> <Compile Include="Devices\ReconfigurableDevice.cs" />
@@ -232,6 +234,7 @@
<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="Occupancy\OccupancyAggregatorConfig.cs" />
<Compile Include="Queues\ComsMessage.cs" /> <Compile Include="Queues\ComsMessage.cs" />
<Compile Include="Queues\ProcessStringMessage.cs" /> <Compile Include="Queues\ProcessStringMessage.cs" />
<Compile Include="Queues\GenericQueue.cs" /> <Compile Include="Queues\GenericQueue.cs" />
@@ -288,6 +291,7 @@
<Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" /> <Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.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\Interfaces.cs" /> <Compile Include="Room\Interfaces.cs" />
<Compile Include="Room\iOccupancyStatusProvider.cs" /> <Compile Include="Room\iOccupancyStatusProvider.cs" />
<Compile Include="Routing\DummyRoutingInputsDevice.cs" /> <Compile Include="Routing\DummyRoutingInputsDevice.cs" />

View File

@@ -375,7 +375,7 @@ namespace PepperDash.Essentials
{ {
try try
{ {
if (typeof (IPluginDeviceFactory).IsAssignableFrom(type)) if (typeof (IPluginDeviceFactory).IsAssignableFrom(type) && !type.IsAbstract)
{ {
var plugin = var plugin =
(IPluginDeviceFactory) Crestron.SimplSharp.Reflection.Activator.CreateInstance(type); (IPluginDeviceFactory) Crestron.SimplSharp.Reflection.Activator.CreateInstance(type);

View File

@@ -38,7 +38,7 @@ namespace PepperDash.Essentials.Core
ScheduledEventGroup FeatureEventGroup; ScheduledEventGroup FeatureEventGroup;
public EssentialsRoomBase Room { get; private set; } public IEssentialsRoom Room { get; private set; }
private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom; private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom;
@@ -84,7 +84,7 @@ namespace PepperDash.Essentials.Core
/// </summary> /// </summary>
void SetUpDevice() void SetUpDevice()
{ {
Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as EssentialsRoomBase; Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IEssentialsRoom;
if (Room != null) if (Room != null)
{ {

View File

@@ -16,7 +16,7 @@ namespace PepperDash.Essentials.Core
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public abstract class EssentialsRoomBase : ReconfigurableDevice public abstract class EssentialsRoomBase : ReconfigurableDevice, IEssentialsRoom
{ {
/// <summary> /// <summary>
/// ///

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Describes the basic functionality of an EssentialsRoom
/// </summary>
public interface IEssentialsRoom : IKeyName, IReconfigurableDevice
{
BoolFeedback OnFeedback { get; }
event EventHandler<EventArgs> RoomOccupancyIsSet;
BoolFeedback IsWarmingUpFeedback { get; }
BoolFeedback IsCoolingDownFeedback { get; }
IOccupancyStatusProvider RoomOccupancy { get; }
bool OccupancyStatusProviderIsRemote { get; }
bool IsMobileControlEnabled { get; }
IMobileControlRoomBridge MobileControlRoomBridge { get; }
string SourceListKey { get; }
SecondsCountdownTimer ShutdownPromptTimer { get; }
int ShutdownPromptSeconds { get; }
int ShutdownVacancySeconds { get; }
eShutdownType ShutdownType { get; }
EssentialsRoomEmergencyBase Emergency { get; }
Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; }
string LogoUrlLightBkgnd { get; }
string LogoUrlDarkBkgnd { get; }
eVacancyMode VacancyMode { get; }
bool ZeroVolumeWhenSwtichingVolumeDevices { get; }
void StartShutdown(eShutdownType type);
void StartRoomVacancyTimer(eVacancyMode mode);
void Shutdown();
void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes);
void PowerOnToDefaultOrLastSource();
bool RunDefaultPresentRoute();
void SetDefaultLevels();
void RoomVacatedForTimeoutPeriod(object o);
}
}

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
@@ -65,4 +66,6 @@ namespace PepperDash.Essentials.Core
bool RunDefaultCallRoute(); bool RunDefaultCallRoute();
} }
} }

View File

@@ -123,14 +123,24 @@ namespace PepperDash.Essentials.Core
// No direct tie? Run back out on the inputs' attached devices... // No direct tie? Run back out on the inputs' attached devices...
// Only the ones that are routing devices // Only the ones that are routing devices
var attachedMidpoints = destDevInputTies.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs); var attachedMidpoints = destDevInputTies.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs);
//Create a list for tracking already checked devices to avoid loops, if it doesn't already exist from previous iteration
if (alreadyCheckedDevices == null)
alreadyCheckedDevices = new List<IRoutingInputsOutputs>();
alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs);
foreach (var inputTieToTry in attachedMidpoints) foreach (var inputTieToTry in attachedMidpoints)
{ {
Debug.Console(2, destination, "Trying to find route on {0}", inputTieToTry.SourcePort.ParentDevice.Key);
var upstreamDeviceOutputPort = inputTieToTry.SourcePort; var upstreamDeviceOutputPort = inputTieToTry.SourcePort;
var upstreamRoutingDevice = upstreamDeviceOutputPort.ParentDevice as IRoutingInputsOutputs; var upstreamRoutingDevice = upstreamDeviceOutputPort.ParentDevice as IRoutingInputsOutputs;
Debug.Console(2, destination, "Trying to find route on {0}", upstreamRoutingDevice.Key);
// Check if this previous device has already been walked // Check if this previous device has already been walked
if (!(alreadyCheckedDevices != null && alreadyCheckedDevices.Contains(upstreamRoutingDevice))) if (alreadyCheckedDevices.Contains(upstreamRoutingDevice))
{ {
Debug.Console(2, destination, "Skipping input {0} on {1}, this was already checked", upstreamRoutingDevice.Key, destination.Key);
continue;
}
// haven't seen this device yet. Do it. Pass the output port to the next // haven't seen this device yet. Do it. Pass the output port to the next
// level to enable switching on success // level to enable switching on success
var upstreamRoutingSuccess = upstreamRoutingDevice.GetRouteToSource(source, upstreamDeviceOutputPort, var upstreamRoutingSuccess = upstreamRoutingDevice.GetRouteToSource(source, upstreamDeviceOutputPort,
@@ -143,7 +153,6 @@ namespace PepperDash.Essentials.Core
} }
} }
} }
}
// we have a route on corresponding inputPort. *** Do the route *** // we have a route on corresponding inputPort. *** Do the route ***
if (goodInputPort != null) if (goodInputPort != null)
@@ -164,10 +173,6 @@ namespace PepperDash.Essentials.Core
return true; return true;
} }
if(alreadyCheckedDevices == null)
alreadyCheckedDevices = new List<IRoutingInputsOutputs>();
alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs);
Debug.Console(2, destination, "No route found to {0}", source.Key); Debug.Console(2, destination, "No route found to {0}", source.Key);
return false; return false;
} }

View File

@@ -1220,7 +1220,7 @@ namespace PepperDash.Essentials.DM
{ {
dmMdMnxn.AudioEnter.BoolValue = true; dmMdMnxn.AudioEnter.BoolValue = true;
} }
output.VideoOut = input; output.AudioOut = input;
//Chassis.Outputs[output].AudioOut = inCard; //Chassis.Outputs[output].AudioOut = inCard;
} }

View File

@@ -8,6 +8,8 @@ using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Presets; using PepperDash.Essentials.Core.Presets;
using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.Codec;
@@ -25,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
Focus = 8 Focus = 8
} }
public abstract class CameraBase : EssentialsDevice, IRoutingOutputs public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs
{ {
public eCameraControlMode ControlMode { get; protected set; } public eCameraControlMode ControlMode { get; protected set; }
@@ -70,12 +72,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
// A bitmasked value to indicate the movement capabilites of this camera // A bitmasked value to indicate the movement capabilites of this camera
protected eCameraCapabilities Capabilities { get; set; } protected eCameraCapabilities Capabilities { get; set; }
protected CameraBase(string key, string name) : protected CameraBase(DeviceConfig config) : base(config)
base(key, name)
{ {
OutputPorts = new RoutingPortCollection<RoutingOutputPort>(); OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
ControlMode = eCameraControlMode.Manual; ControlMode = eCameraControlMode.Manual;
}
protected CameraBase(string key, string name) :
this (new DeviceConfig{Name = name, Key = key})
{
} }
protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey, protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey,

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

@@ -4,15 +4,20 @@ using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using PepperDash.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec namespace PepperDash.Essentials.Devices.Common.Codec
{ {
[Flags]
public enum eMeetingEventChangeType public enum eMeetingEventChangeType
{ {
Unkown = 0, Unknown = 0,
MeetingStartWarning, MeetingStartWarning = 1,
MeetingStart, MeetingStart = 2,
MeetingEndWarning, MeetingEndWarning = 4,
MeetingEnd MeetingEnd = 8
} }
public interface IHasScheduleAwareness public interface IHasScheduleAwareness
@@ -32,6 +37,10 @@ namespace PepperDash.Essentials.Devices.Common.Codec
private int _meetingWarningMinutes = 5; private int _meetingWarningMinutes = 5;
private Meeting _previousChangedMeeting;
private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown;
public int MeetingWarningMinutes public int MeetingWarningMinutes
{ {
get { return _meetingWarningMinutes; } get { return _meetingWarningMinutes; }
@@ -75,38 +84,72 @@ namespace PepperDash.Essentials.Devices.Common.Codec
_scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime); _scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime);
} }
/// <summary>
/// Helper method to fire MeetingEventChange. Should only fire once for each changeType on each meeting
/// </summary>
/// <param name="changeType"></param>
/// <param name="meeting"></param>
private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting) private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting)
{ {
Debug.Console(2, "*****************OnMeetingChange. id: {0} changeType: {1}**********************", meeting.Id, changeType);
if (changeType != (changeType & meeting.NotifiedChangeTypes))
{
// Add this change type to the NotifiedChangeTypes
meeting.NotifiedChangeTypes |= changeType;
var handler = MeetingEventChange; var handler = MeetingEventChange;
if (handler != null) if (handler != null)
{ {
handler(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting }); handler(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
} }
} }
else
private void CheckSchedule(object o)
{ {
// Iterate the meeting list and check if any meeting need to do anythingk Debug.Console(2, "Meeting: {0} already notified of changeType: {1}", meeting.Id, changeType);
}
const double meetingTimeEpsilon = 0.0001;
foreach (var m in Meetings)
{
var changeType = eMeetingEventChangeType.Unkown;
if (m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to start
changeType = eMeetingEventChangeType.MeetingStartWarning;
else if (Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start
changeType = eMeetingEventChangeType.MeetingStart;
else if (m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to end
changeType = eMeetingEventChangeType.MeetingEndWarning;
else if (Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended
changeType = eMeetingEventChangeType.MeetingEnd;
if (changeType != eMeetingEventChangeType.Unkown)
OnMeetingChange(changeType, m);
} }
/// <summary>
/// Checks the schedule to see if any MeetingEventChange updates should be fired
/// </summary>
/// <param name="o"></param>
private void CheckSchedule(object o)
{
// Iterate the meeting list and check if any meeting need to do anything
const double meetingTimeEpsilon = 0.05;
foreach (var m in Meetings)
{
var changeType = eMeetingEventChangeType.Unknown;
if (eMeetingEventChangeType.MeetingStartWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStartWarning) && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start
{
Debug.Console(2, "********************* MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds);
changeType = eMeetingEventChangeType.MeetingStartWarning;
}
else if (eMeetingEventChangeType.MeetingStart != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStart) && Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start
{
Debug.Console(2, "********************* MeetingStart");
changeType = eMeetingEventChangeType.MeetingStart;
}
else if (eMeetingEventChangeType.MeetingEndWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEndWarning) && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end
{
Debug.Console(2, "********************* MeetingEndWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingEnd.TotalMinutes, m.TimeToMeetingEnd.Seconds);
changeType = eMeetingEventChangeType.MeetingEndWarning;
}
else if (eMeetingEventChangeType.MeetingEnd != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEnd) && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended
{
Debug.Console(2, "********************* MeetingEnd");
changeType = eMeetingEventChangeType.MeetingEnd;
}
if (changeType != eMeetingEventChangeType.Unknown)
{
OnMeetingChange(changeType, m);
}
}
} }
} }
@@ -115,17 +158,24 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary> /// </summary>
public class Meeting public class Meeting
{ {
[JsonProperty("minutesBeforeMeeting")]
public int MinutesBeforeMeeting; public int MinutesBeforeMeeting;
[JsonProperty("id")]
public string Id { get; set; } public string Id { get; set; }
[JsonProperty("organizer")]
public string Organizer { get; set; } public string Organizer { get; set; }
[JsonProperty("title")]
public string Title { get; set; } public string Title { get; set; }
[JsonProperty("agenda")]
public string Agenda { get; set; } public string Agenda { get; set; }
[JsonProperty("meetingWarningMinutes")]
public TimeSpan MeetingWarningMinutes public TimeSpan MeetingWarningMinutes
{ {
get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); } get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); }
} }
[JsonProperty("timeToMeetingStart")]
public TimeSpan TimeToMeetingStart public TimeSpan TimeToMeetingStart
{ {
get get
@@ -133,6 +183,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
return StartTime - DateTime.Now; return StartTime - DateTime.Now;
} }
} }
[JsonProperty("timeToMeetingEnd")]
public TimeSpan TimeToMeetingEnd public TimeSpan TimeToMeetingEnd
{ {
get get
@@ -140,8 +191,11 @@ namespace PepperDash.Essentials.Devices.Common.Codec
return EndTime - DateTime.Now; return EndTime - DateTime.Now;
} }
} }
[JsonProperty("startTime")]
public DateTime StartTime { get; set; } public DateTime StartTime { get; set; }
[JsonProperty("endTime")]
public DateTime EndTime { get; set; } public DateTime EndTime { get; set; }
[JsonProperty("duration")]
public TimeSpan Duration public TimeSpan Duration
{ {
get get
@@ -149,21 +203,34 @@ namespace PepperDash.Essentials.Devices.Common.Codec
return EndTime - StartTime; return EndTime - StartTime;
} }
} }
[JsonProperty("privacy")]
public eMeetingPrivacy Privacy { get; set; } public eMeetingPrivacy Privacy { get; set; }
[JsonProperty("joinable")]
public bool Joinable public bool Joinable
{ {
get get
{ {
return StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now
&& DateTime.Now <= EndTime; //.AddMinutes(-5); && DateTime.Now <= EndTime.AddMinutes(-5);
//Debug.Console(2, "Meeting Id: {0} joinable: {1}", Id, joinable);
return joinable;
} }
} }
//public string ConferenceNumberToDial { get; set; } //public string ConferenceNumberToDial { get; set; }
[JsonProperty("conferencePassword")]
public string ConferencePassword { get; set; } public string ConferencePassword { get; set; }
[JsonProperty("isOneButtonToPushMeeting")]
public bool IsOneButtonToPushMeeting { get; set; } public bool IsOneButtonToPushMeeting { get; set; }
[JsonProperty("calls")]
public List<Call> Calls { get; private set; } public List<Call> Calls { get; private set; }
/// <summary>
/// Tracks the change types that have already been notified for
/// </summary>
[JsonIgnore]
public eMeetingEventChangeType NotifiedChangeTypes { get; set; }
public Meeting() public Meeting()
{ {
Calls = new List<Call>(); Calls = new List<Call>();

View File

@@ -122,6 +122,7 @@
<Compile Include="Display\PanasonicThDisplay.cs" /> <Compile Include="Display\PanasonicThDisplay.cs" />
<Compile Include="VideoCodec\Interfaces\IHasParticipants.cs" /> <Compile Include="VideoCodec\Interfaces\IHasParticipants.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" /> <Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewSize.cs" />
<Compile Include="VideoCodec\Interfaces\iVideoCodecInfo.cs" /> <Compile Include="VideoCodec\Interfaces\iVideoCodecInfo.cs" />
<Compile Include="Codec\iHasCallFavorites.cs" /> <Compile Include="Codec\iHasCallFavorites.cs" />
<Compile Include="Codec\iHasCallHistory.cs" /> <Compile Include="Codec\iHasCallHistory.cs" />
@@ -176,6 +177,7 @@
<Compile Include="VideoCodec\ZoomRoom\ResponseObjects.cs" /> <Compile Include="VideoCodec\ZoomRoom\ResponseObjects.cs" />
<Compile Include="VideoCodec\ZoomRoom\ZoomRoom.cs" /> <Compile Include="VideoCodec\ZoomRoom\ZoomRoom.cs" />
<Compile Include="VideoCodec\ZoomRoom\ZoomRoomCamera.cs" /> <Compile Include="VideoCodec\ZoomRoom\ZoomRoomCamera.cs" />
<Compile Include="VideoCodec\ZoomRoom\ZoomRoomJoinMap.cs" />
<Compile Include="VideoCodec\ZoomRoom\ZoomRoomPropertiesConfig.cs" /> <Compile Include="VideoCodec\ZoomRoom\ZoomRoomPropertiesConfig.cs" />
<None Include="Properties\ControlSystem.cfg" /> <None Include="Properties\ControlSystem.cfg" />
</ItemGroup> </ItemGroup>

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;

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

View File

@@ -19,4 +19,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
void LocalLayoutToggleSingleProminent(); void LocalLayoutToggleSingleProminent();
void MinMaxLayoutToggle(); void MinMaxLayoutToggle();
} }
/// <summary>
/// Defines the requirements for Zoom Room layout control
/// </summary>
public interface IHasZoomRoomLayouts : IHasCodecLayouts
{
event EventHandler<LayoutInfoChangedEventArgs> AvailableLayoutsChanged;
BoolFeedback LayoutViewIsOnFirstPageFeedback { get; } // TODO: #697 [*] Consider modifying to report button visibility in func
BoolFeedback LayoutViewIsOnLastPageFeedback { get; } // TODO: #697 [*] Consider modifying to report button visibility in func
BoolFeedback CanSwapContentWithThumbnailFeedback { get; }
BoolFeedback ContentSwappedWithThumbnailFeedback { get; }
ZoomRoom.zConfiguration.eLayoutStyle LastSelectedLayout { get; }
ZoomRoom.zConfiguration.eLayoutStyle AvailableLayouts { get; }
void GetAvailableLayouts(); // Mot sure this is necessary if we're already subscribed to zStatus Call Layout
void SetLayout(ZoomRoom.zConfiguration.eLayoutStyle layoutStyle);
void SwapContentWithThumbnail();
void LayoutTurnNextPage();
void LayoutTurnPreviousPage();
}
public class LayoutInfoChangedEventArgs : EventArgs
{
public ZoomRoom.zConfiguration.eLayoutStyle AvailableLayouts { get; set; }
}
} }

View File

@@ -1,13 +1,20 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{ {
/// <summary>
/// Describes a device that has call participants
/// </summary>
public interface IHasParticipants public interface IHasParticipants
{ {
CodecParticipants Participants { get; } CodecParticipants Participants { get; }
} }
/// <summary>
/// Describes the ability to mute and unmute a participant's video in a meeting
/// </summary>
public interface IHasParticipantVideoMute:IHasParticipants public interface IHasParticipantVideoMute:IHasParticipants
{ {
void MuteVideoForParticipant(int userId); void MuteVideoForParticipant(int userId);
@@ -15,6 +22,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
void ToggleVideoForParticipant(int userId); void ToggleVideoForParticipant(int userId);
} }
/// <summary>
/// Describes the ability to mute and unmute a participant's audio in a meeting
/// </summary>
public interface IHasParticipantAudioMute : IHasParticipantVideoMute public interface IHasParticipantAudioMute : IHasParticipantVideoMute
{ {
void MuteAudioForParticipant(int userId); void MuteAudioForParticipant(int userId);
@@ -22,6 +32,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
void ToggleAudioForParticipant(int userId); void ToggleAudioForParticipant(int userId);
} }
/// <summary>
/// Describes the ability to pin and unpin a participant in a meeting
/// </summary>
public interface IHasParticipantPinUnpin : IHasParticipants
{
IntFeedback NumberOfScreensFeedback { get; }
int ScreenIndexToPinUserTo { get; }
void PinParticipant(int userId, int screenIndex);
void UnPinParticipant(int userId);
void ToggleParticipantPinState(int userId, int screenIndex);
}
public class CodecParticipants public class CodecParticipants
{ {
private List<Participant> _currentParticipants; private List<Participant> _currentParticipants;
@@ -31,11 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
set set
{ {
_currentParticipants = value; _currentParticipants = value;
var handler = ParticipantsListHasChanged; OnParticipantsChanged();
if(handler == null) return;
handler(this, new EventArgs());
} }
} }
@@ -45,15 +64,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{ {
_currentParticipants = new List<Participant>(); _currentParticipants = new List<Participant>();
} }
public void OnParticipantsChanged()
{
var handler = ParticipantsListHasChanged;
if (handler == null) return;
handler(this, new EventArgs());
}
} }
/// <summary>
/// Represents a call participant
/// </summary>
public class Participant public class Participant
{ {
public int UserId { get; set; }
public bool IsHost { get; set; } public bool IsHost { get; set; }
public string Name { get; set; } public string Name { get; set; }
public bool CanMuteVideo { get; set; } public bool CanMuteVideo { get; set; }
public bool CanUnmuteVideo { get; set; } public bool CanUnmuteVideo { get; set; }
public bool VideoMuteFb { get; set; } public bool VideoMuteFb { get; set; }
public bool AudioMuteFb { get; set; } public bool AudioMuteFb { get; set; }
public bool HandIsRaisedFb { get; set; }
public bool IsPinnedFb { get; set; }
public int ScreenIndexIsPinnedToFb { get; set; }
public Participant()
{
// Initialize to -1 (no screen)
ScreenIndexIsPinnedToFb = -1;
}
} }
} }

View File

@@ -0,0 +1,13 @@
using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
public interface IHasSelfviewSize
{
StringFeedback SelfviewPipSizeFeedback { get; }
void SelfviewPipSizeSet(CodecCommandWithLabel size);
void SelfviewPipSizeToggle();
}
}

View File

@@ -139,7 +139,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public override void Dial(Meeting meeting) public override void Dial(Meeting meeting)
{ {
throw new NotImplementedException(); Debug.Console(1, this, "Dial Meeting: {0}", meeting.Id);
var call = new CodecActiveCallItem() { Name = meeting.Title, Number = meeting.Id, Id = meeting.Id, Status = eCodecCallStatus.Dialing, Direction = eCodecCallDirection.Outgoing, Type = eCodecCallType.Video };
ActiveCalls.Add(call);
OnCallStatusChange(call);
//ActiveCallCountFeedback.FireUpdate();
// Simulate 2-second ring, then connecting, then connected
new CTimer(o =>
{
call.Type = eCodecCallType.Video;
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call);
new CTimer(oo => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000);
}, 2000);
} }
/// <summary> /// <summary>
@@ -396,12 +409,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
if (_CodecSchedule == null || _CodecSchedule.Meetings.Count == 0 if (_CodecSchedule == null || _CodecSchedule.Meetings.Count == 0
|| _CodecSchedule.Meetings[_CodecSchedule.Meetings.Count - 1].StartTime < DateTime.Now) || _CodecSchedule.Meetings[_CodecSchedule.Meetings.Count - 1].StartTime < DateTime.Now)
{ {
_CodecSchedule = new CodecScheduleAwareness(); _CodecSchedule = new CodecScheduleAwareness(1000);
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
var m = new Meeting(); var m = new Meeting();
m.StartTime = DateTime.Now.AddMinutes(3).AddHours(i); m.MinutesBeforeMeeting = 5;
m.EndTime = DateTime.Now.AddHours(i).AddMinutes(30); m.Id = i.ToString();
m.Organizer = "Employee " + 1;
m.StartTime = DateTime.Now.AddMinutes(6).AddHours(i);
m.EndTime = DateTime.Now.AddHours(i).AddMinutes(16);
m.Title = "Meeting " + i; m.Title = "Meeting " + i;
m.Calls.Add(new Call() { Number = i + "meeting@fake.com"}); m.Calls.Add(new Call() { Number = i + "meeting@fake.com"});
_CodecSchedule.Meetings.Add(m); _CodecSchedule.Meetings.Add(m);

View File

@@ -28,6 +28,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced
{ {
private const int XSigEncoding = 28591; private const int XSigEncoding = 28591;
protected const int MaxParticipants = 50;
private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs(); private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs();
protected VideoCodecBase(DeviceConfig config) protected VideoCodecBase(DeviceConfig config)
: base(config) : base(config)
@@ -64,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; }
@@ -271,6 +272,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
/// <summary>
/// Use this method when using a plain VideoCodecControllerJoinMap
/// </summary>
/// <param name="codec"></param>
/// <param name="trilist"></param>
/// <param name="joinStart"></param>
/// <param name="joinMapKey"></param>
/// <param name="bridge"></param>
protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, uint joinStart, string joinMapKey, protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, uint joinStart, string joinMapKey,
EiscApiAdvanced bridge) EiscApiAdvanced bridge)
{ {
@@ -288,10 +297,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
bridge.AddJoinMap(Key, joinMap); bridge.AddJoinMap(Key, joinMap);
} }
LinkVideoCodecToApi(codec, trilist, joinMap);
}
/// <summary>
/// Use this method when you need to pass in a join map that extends VideoCodecControllerJoinMap
/// </summary>
/// <param name="codec"></param>
/// <param name="trilist"></param>
/// <param name="joinMap"></param>
protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
Debug.Console(1, this, "Linking to Trilist {0}", trilist.ID.ToString("X")); Debug.Console(1, this, "Linking to Trilist {0}", trilist.ID.ToString("X"));
LinkVideoCodecDtmfToApi(trilist, joinMap); LinkVideoCodecDtmfToApi(trilist, joinMap);
LinkVideoCodecCallControlsToApi(trilist, joinMap); LinkVideoCodecCallControlsToApi(trilist, joinMap);
@@ -512,7 +530,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
private void LinkVideoCodecParticipantsToApi(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void LinkVideoCodecParticipantsToApi(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{ {
// make sure to update the values when the EISC comes online
trilist.OnlineStatusChange += (sender, args) =>
{
if (sender.IsOnline)
{
UpdateParticipantsXSig(codec, trilist, joinMap);
}
};
// set actions and update the values when the list changes
codec.Participants.ParticipantsListHasChanged += (sender, args) => codec.Participants.ParticipantsListHasChanged += (sender, args) =>
{
SetParticipantActions(trilist, joinMap, codec.Participants.CurrentParticipants);
UpdateParticipantsXSig(codec, trilist, joinMap);
};
}
private void UpdateParticipantsXSig(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{ {
string participantsXSig; string participantsXSig;
@@ -529,17 +565,61 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig); trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig);
trilist.SetUshort(joinMap.ParticipantCount.JoinNumber, (ushort)codec.Participants.CurrentParticipants.Count); trilist.SetUshort(joinMap.ParticipantCount.JoinNumber, (ushort)codec.Participants.CurrentParticipants.Count);
}; }
/// <summary>
/// Sets the actions for each participant in the list
/// </summary>
private void SetParticipantActions(BasicTriList trilist, VideoCodecControllerJoinMap joinMap, List<Participant> currentParticipants)
{
uint index = 0; // track the index of the participant in the
foreach (var participant in currentParticipants)
{
var p = participant;
if (index > MaxParticipants) break;
var audioMuteCodec = this as IHasParticipantAudioMute;
if (audioMuteCodec != null)
{
trilist.SetSigFalseAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index,
() => audioMuteCodec.ToggleAudioForParticipant(p.UserId));
trilist.SetSigFalseAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index,
() => audioMuteCodec.ToggleVideoForParticipant(p.UserId));
}
var pinCodec = this as IHasParticipantPinUnpin;
if (pinCodec != null)
{
trilist.SetSigFalseAction(joinMap.ParticipantPinToggleStart.JoinNumber + index,
() => pinCodec.ToggleParticipantPinState(p.UserId, pinCodec.ScreenIndexToPinUserTo));
}
index++;
}
// Clear out any previously set actions
while (index < MaxParticipants)
{
trilist.ClearBoolSigAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index);
trilist.ClearBoolSigAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index);
trilist.ClearBoolSigAction(joinMap.ParticipantPinToggleStart.JoinNumber + index);
index++;
}
} }
private string UpdateParticipantsXSig(List<Participant> currentParticipants) private string UpdateParticipantsXSig(List<Participant> currentParticipants)
{ {
const int maxParticipants = 50; const int maxParticipants = MaxParticipants;
const int maxDigitals = 5; const int maxDigitals = 7;
const int maxStrings = 1; const int maxStrings = 1;
const int offset = maxDigitals + maxStrings; const int maxAnalogs = 1;
var digitalIndex = maxStrings * maxParticipants; //15 const int offset = maxDigitals + maxStrings + maxAnalogs; // 9
var digitalIndex = (maxStrings + maxAnalogs) * maxParticipants; // 100
var stringIndex = 0; var stringIndex = 0;
var analogIndex = stringIndex + maxParticipants;
var meetingIndex = 0; var meetingIndex = 0;
var tokenArray = new XSigToken[maxParticipants * offset]; var tokenArray = new XSigToken[maxParticipants * offset];
@@ -548,38 +628,91 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{ {
if (meetingIndex >= maxParticipants * offset) break; if (meetingIndex >= maxParticipants * offset) break;
Debug.Console(2, this,
@"Updating Participant on xsig:
Name: {0} (s{9})
AudioMute: {1} (d{10})
VideoMute: {2} (d{11})
CanMuteVideo: {3} (d{12})
CanUMuteVideo: {4} (d{13})
IsHost: {5} (d{14})
HandIsRaised: {6} (d{15})
IsPinned: {7} (d{16})
ScreenIndexIsPinnedTo: {8} (a{17})
",
participant.Name,
participant.AudioMuteFb,
participant.VideoMuteFb,
participant.CanMuteVideo,
participant.CanUnmuteVideo,
participant.IsHost,
participant.HandIsRaisedFb,
participant.IsPinnedFb,
participant.ScreenIndexIsPinnedToFb,
stringIndex + 1,
digitalIndex + 1,
digitalIndex + 2,
digitalIndex + 3,
digitalIndex + 4,
digitalIndex + 5,
digitalIndex + 6,
digitalIndex + 7,
analogIndex + 1
);
//digitals //digitals
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, participant.AudioMuteFb); tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, participant.AudioMuteFb);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, participant.VideoMuteFb); tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, participant.VideoMuteFb);
tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, participant.CanMuteVideo); tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, participant.CanMuteVideo);
tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, participant.CanUnmuteVideo); tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, participant.CanUnmuteVideo);
tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, participant.IsHost); tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, participant.IsHost);
tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, participant.HandIsRaisedFb);
tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, participant.IsPinnedFb);
Debug.Console(2, this, "Index: {0} byte value: {1}", digitalIndex + 7, ComTextHelper.GetEscapedText(tokenArray[digitalIndex + 6].GetBytes()));
//serials //serials
tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, participant.Name); tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, participant.Name);
//analogs
tokenArray[analogIndex] = new XSigAnalogToken(analogIndex + 1, (ushort)participant.ScreenIndexIsPinnedToFb);
digitalIndex += maxDigitals; digitalIndex += maxDigitals;
meetingIndex += offset; meetingIndex += offset;
stringIndex += maxStrings; stringIndex += maxStrings;
analogIndex += maxAnalogs;
} }
while (meetingIndex < maxParticipants * offset) while (meetingIndex < maxParticipants * offset)
{ {
//digitals
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false);
tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, false); tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, false);
tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, false); tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, false);
tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, false); tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, false);
tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, false);
tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, false);
//serials //serials
tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty);
//analogs
tokenArray[analogIndex] = new XSigAnalogToken(analogIndex + 1, 0);
digitalIndex += maxDigitals; digitalIndex += maxDigitals;
meetingIndex += offset; meetingIndex += offset;
stringIndex += maxStrings; stringIndex += maxStrings;
analogIndex += maxAnalogs;
} }
return GetXSigString(tokenArray); var returnString = GetXSigString(tokenArray);
//Debug.Console(2, this, "{0}", ComTextHelper.GetEscapedText(Encoding.GetEncoding(28591).GetBytes(returnString)));
return returnString;
} }
private void LinkVideoCodecContentSharingToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void LinkVideoCodecContentSharingToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
@@ -595,7 +728,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, (b) => AutoShareContentWhileInCall = b); trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, (b) => AutoShareContentWhileInCall = b);
} }
// TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues
private List<Meeting> _currentMeetings = new List<Meeting>(); private List<Meeting> _currentMeetings = new List<Meeting>();
private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
@@ -607,7 +739,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
codec.CodecSchedule.MeetingWarningMinutes = i; codec.CodecSchedule.MeetingWarningMinutes = i;
}); });
// TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues
trilist.SetSigFalseAction(joinMap.DialMeeting1.JoinNumber, () => trilist.SetSigFalseAction(joinMap.DialMeeting1.JoinNumber, () =>
{ {
var mtg = 1; var mtg = 1;
@@ -617,7 +748,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
if (_currentMeetings[index] != null) if (_currentMeetings[index] != null)
Dial(_currentMeetings[index]); Dial(_currentMeetings[index]);
}); });
// TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues
trilist.SetSigFalseAction(joinMap.DialMeeting2.JoinNumber, () => trilist.SetSigFalseAction(joinMap.DialMeeting2.JoinNumber, () =>
{ {
var mtg = 2; var mtg = 2;
@@ -627,7 +758,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
if (_currentMeetings[index] != null) if (_currentMeetings[index] != null)
Dial(_currentMeetings[index]); Dial(_currentMeetings[index]);
}); });
// TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues
trilist.SetSigFalseAction(joinMap.DialMeeting3.JoinNumber, () => trilist.SetSigFalseAction(joinMap.DialMeeting3.JoinNumber, () =>
{ {
var mtg = 3; var mtg = 3;
@@ -652,14 +783,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{ {
var currentTime = DateTime.Now; var currentTime = DateTime.Now;
// TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues
// - changed var currentMeetings >> field _currentMeetings
//_currentMeetings.Clear();
_currentMeetings = codec.CodecSchedule.Meetings.Where(m => m.StartTime >= currentTime || m.EndTime >= currentTime).ToList(); _currentMeetings = codec.CodecSchedule.Meetings.Where(m => m.StartTime >= currentTime || m.EndTime >= currentTime).ToList();
// TODO [ ] 2021-01-06, jkd: Added to debug OBTP dialing issues
// - moved the trilist.SetSigFlaseAction(joinMap.DialMeeting1..3.JoinNumber) lambda's to LinkVideoCodecScheduleToApi
var meetingsData = UpdateMeetingsListXSig(_currentMeetings); var meetingsData = UpdateMeetingsListXSig(_currentMeetings);
trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData);
trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count); trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count);

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);
@@ -480,12 +487,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public string wifiName { get; set; } public string wifiName { get; set; }
} }
public class NumberOfScreens public class NumberOfScreens : NotifiableObject
{ {
private int _numOfScreens;
[JsonProperty("NumberOfCECScreens")] [JsonProperty("NumberOfCECScreens")]
public int NumOfCECScreens { get; set; } public int NumOfCECScreens { get; set; }
[JsonProperty("NumberOfScreens")] [JsonProperty("NumberOfScreens")]
public int NumOfScreens { get; set; } public int NumOfScreens
{
get
{
return _numOfScreens;
}
set
{
if (value != _numOfScreens)
{
_numOfScreens = value;
NotifyPropertyChanged("NumberOfScreens");
}
}
}
} }
/// <summary> /// <summary>
@@ -551,18 +574,136 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
public class Layout public class Layout : NotifiableObject
{ {
// backer variables
private bool _can_Switch_Speaker_View;
private bool _can_Switch_Wall_View;
private bool _can_Switch_Share_On_All_Screens;
private bool _is_In_First_Page;
private bool _is_In_Last_Page;
private string _video_type;
public bool can_Adjust_Floating_Video { get; set; } public bool can_Adjust_Floating_Video { get; set; }
public bool can_Switch_Floating_Share_Content { get; set; } public bool can_Switch_Floating_Share_Content { get; set; }
public bool can_Switch_Share_On_All_Screens { get; set; }
public bool can_Switch_Speaker_View { get; set; } /// <summary>
public bool can_Switch_Wall_View { get; set; } /// [on/off] // Set to On if it is possible to invoke zConfiguration Call Layout Style: ShareAll, to switch to the ShareAll mode, where the content sharing is shown full screen on all monitors.
public bool is_In_First_Page { get; set; } /// </summary>
public bool is_In_Last_Page { get; set; } [JsonProperty("can_Switch_Share_On_All_Screens")]
public bool can_Switch_Share_On_All_Screens
{
get
{
return _can_Switch_Share_On_All_Screens;
}
set
{
if (value != _can_Switch_Share_On_All_Screens)
{
_can_Switch_Share_On_All_Screens = value;
NotifyPropertyChanged("can_Switch_Share_On_All_Screens");
}
}
}
/// <summary>
/// [on/off] // Set to On if it is possible to switch to Speaker view by invoking zConfiguration Call Layout Style: Speaker. The active speaker is shown full screen, and other video streams, like self-view, are shown in thumbnails.
/// </summary>
[JsonProperty("can_Switch_Speaker_View")]
public bool can_Switch_Speaker_View
{
get
{
return _can_Switch_Speaker_View;
}
set
{
if (value != _can_Switch_Speaker_View)
{
_can_Switch_Speaker_View = value;
NotifyPropertyChanged("can_Switch_Speaker_View");
}
}
}
/// <summary>
/// [on/off] On if it is possible to invoke zConfiguration Call Layout Style: Gallery, to switch to the Gallery mode, showing video participants in tiled windows: The Zoom Room shows up to a 5x5 array of tiled windows per page.
/// </summary>
[JsonProperty("can_Switch_Wall_View")]
public bool can_Switch_Wall_View
{
get
{
return _can_Switch_Wall_View;
}
set
{
if (value != _can_Switch_Wall_View)
{
_can_Switch_Wall_View = value;
NotifyPropertyChanged("can_Switch_Wall_View");
}
}
}
[JsonProperty("is_In_First_Page")]
public bool is_In_First_Page
{
get
{
return _is_In_First_Page;
}
set
{
if (value != _is_In_First_Page)
{
_is_In_First_Page = value;
NotifyPropertyChanged("is_In_First_Page");
}
}
}
[JsonProperty("is_In_Last_Page")]
public bool is_In_Last_Page
{
get
{
return _is_In_Last_Page;
}
set
{
if (value != _is_In_Last_Page)
{
_is_In_Last_Page = value;
NotifyPropertyChanged("is_In_Last_Page");
}
}
}
public bool is_supported { get; set; } public bool is_supported { get; set; }
public int video_Count_In_Current_Page { get; set; } public int video_Count_In_Current_Page { get; set; }
public string video_type { get; set; }
/// <summary>
/// [Gallery | Strip] Indicates which mode applies: Strip or Gallery.
/// </summary>
[JsonProperty("video_type")]
public string video_type
{
get
{
return _video_type;
}
set
{
if (value != _video_type)
{
_video_type = value;
NotifyPropertyChanged("video_type");
}
}
}
} }
public class CallRecordInfo public class CallRecordInfo
@@ -685,6 +826,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public class PinStatusOfScreenNotification public class PinStatusOfScreenNotification
{ {
[JsonProperty("can_be_pinned")] [JsonProperty("can_be_pinned")]
public bool CanBePinned { get; set; } public bool CanBePinned { get; set; }
[JsonProperty("can_pin_share")] [JsonProperty("can_pin_share")]
@@ -712,7 +855,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private bool _offHook; private bool _offHook;
public string CallId { get; set; } public string CallId { get; set; }
public bool IsIncomingCall { public bool IsIncomingCall
{
get { return _isIncomingCall; } get { return _isIncomingCall; }
set set
{ {
@@ -720,7 +864,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_isIncomingCall = value; _isIncomingCall = value;
NotifyPropertyChanged("IsIncomingCall"); NotifyPropertyChanged("IsIncomingCall");
} } }
}
public string PeerDisplayName public string PeerDisplayName
{ {
@@ -835,12 +980,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
} }
[Flags]
public enum eLayoutStyle public enum eLayoutStyle
{ {
Gallery, None = 0,
Speaker, Gallery = 1,
Strip, Speaker = 2,
ShareAll Strip = 4,
ShareAll = 8,
} }
public enum eLayoutSize public enum eLayoutSize
@@ -867,18 +1014,62 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public class Layout : NotifiableObject public class Layout : NotifiableObject
{ {
public bool ShareThumb { get; set; } private bool _shareThumb;
public eLayoutStyle Style { get; set; } private eLayoutStyle _style;
public eLayoutSize Size { get; set; } private eLayoutSize _size;
private eLayoutPosition _position; private eLayoutPosition _position;
public eLayoutPosition Position {
public bool ShareThumb
{
get { return _shareThumb; }
set
{
if (value != _shareThumb)
{
_shareThumb = value;
NotifyPropertyChanged("ShareThumb");
}
}
}
public eLayoutStyle Style
{
get { return _style; }
set
{
if (value != _style)
{
_style = value;
NotifyPropertyChanged("Style");
}
}
}
public eLayoutSize Size
{
get { return _size; }
set
{
if (value != _size)
{
_size = value;
NotifyPropertyChanged("Size");
}
}
}
public eLayoutPosition Position
{
get { return _position; } get { return _position; }
set set
{
if (value != _position)
{ {
_position = value; _position = value;
NotifyPropertyChanged("Position"); NotifyPropertyChanged("Position");
} } }
}
}
} }
public class Lock public class Lock
@@ -977,11 +1168,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
set set
{ {
if (value != _hideConfSelfVideo) //if (value != _hideConfSelfVideo)
{ //{
_hideConfSelfVideo = value; _hideConfSelfVideo = value;
NotifyPropertyChanged("HideConfSelfVideo"); NotifyPropertyChanged("HideConfSelfVideo");
} //}
} }
} }
@@ -998,7 +1189,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private string _selectedId; private string _selectedId;
[JsonProperty("selectedId")] [JsonProperty("selectedId")]
public string SelectedId { public string SelectedId
{
get get
{ {
return _selectedId; return _selectedId;
@@ -1020,6 +1212,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
public string appVersion { get; set; } public string appVersion { get; set; }
public string deviceSystem { get; set; } public string deviceSystem { get; set; }
// This doesn't belong here, but there's a bug in the object structure of Zoom Room 5.6.3 that puts it here
public zConfiguration.Call Call { get; set; }
public Client()
{
Call = new zConfiguration.Call();
}
} }
} }
@@ -1135,14 +1335,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public class HandStatus public class HandStatus
{ {
[JsonProperty("is_raise_hand")] // example return of the "hand_status" object
// !!!! Note the properties contain ': ' within the property name !!!
//"hand_status": {
// "is_raise_hand: ": false,
// "is_valid: ": "on",
// "time_stamp: ": "11825083"
//},
[JsonProperty("is_raise_hand: ")]
public bool IsRaiseHand { get; set; } public bool IsRaiseHand { get; set; }
[JsonProperty("optimize_vis_validideo_sharing")] [JsonProperty("is_valid: ")]
public string IsValid { get; set; } public string IsValid { get; set; }
[JsonProperty("time_stamp")] [JsonProperty("time_stamp: ")]
public string TimeStamp { get; set; } public string TimeStamp { get; set; }
/// <summary>
/// Retuns a boolean value if the participant hand state is raised and is valid (both need to be true)
/// </summary>
public bool HandIsRaisedAndValid
{
get { return IsValid != null && IsValid == "on" && IsRaiseHand; }
}
} }
public class ListParticipant public class ListParticipant
{ {
[JsonProperty("audio_status state")] [JsonProperty("audio_status state")]
@@ -1205,22 +1418,87 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
HandStatus = new HandStatus(); HandStatus = new HandStatus();
} }
/// <summary>
/// Converts ZoomRoom pariticpant list response to an Essentials participant list
/// </summary>
/// <param name="participants"></param>
/// <returns></returns>
public static List<Participant> GetGenericParticipantListFromParticipantsResult( public static List<Participant> GetGenericParticipantListFromParticipantsResult(
List<ListParticipant> participants) List<ListParticipant> participants)
{ {
return //return participants.Select(p => new Participant
participants.Select( // {
p => // UserId = p.UserId,
new Participant // Name = p.UserName,
// IsHost = p.IsHost,
// CanMuteVideo = p.IsVideoCanMuteByHost,
// CanUnmuteVideo = p.IsVideoCanUnmuteByHost,
// AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED",
// VideoMuteFb = p.VideoStatusIsSending,
// HandIsRaisedFb = p.HandStatus.HandIsRaisedAndValid,
// }).ToList();
var sortedParticipants = SortParticipantListByHandStatus(participants);
return sortedParticipants.Select(p => new Participant
{ {
UserId = p.UserId,
Name = p.UserName, Name = p.UserName,
IsHost = p.IsHost, IsHost = p.IsHost,
CanMuteVideo = p.IsVideoCanMuteByHost, CanMuteVideo = p.IsVideoCanMuteByHost,
CanUnmuteVideo = p.IsVideoCanUnmuteByHost, CanUnmuteVideo = p.IsVideoCanUnmuteByHost,
AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED", AudioMuteFb = p.AudioStatusState == "AUDIO_MUTED",
VideoMuteFb = p.VideoStatusIsSending VideoMuteFb = !p.VideoStatusIsSending,
HandIsRaisedFb = p.HandStatus.HandIsRaisedAndValid,
}).ToList(); }).ToList();
} }
/// <summary>
/// Will sort by hand-raise status and then alphabetically
/// </summary>
/// <param name="participants">Zoom Room response list of participants</param>
/// <returns>List</returns>
public static List<ListParticipant> SortParticipantListByHandStatus(List<ListParticipant> participants)
{
if (participants == null)
{
//Debug.Console(1, "SortParticiapntListByHandStatu(participants == null)");
return null;
}
// debug testing
//foreach (ListParticipant participant in participants)
//{
// Debug.Console(1, "{0} | IsValid: {1} | IsRaiseHand: {2} | HandIsRaisedAndValid: {3}",
// participant.UserName, participant.HandStatus.IsValid, participant.HandStatus.IsRaiseHand.ToString(), participant.HandStatus.HandIsRaisedAndValid.ToString());
//}
List<ListParticipant> handRaisedParticipantsList = participants.Where(p => p.HandStatus.HandIsRaisedAndValid).ToList();
if (handRaisedParticipantsList != null)
{
IOrderedEnumerable<ListParticipant> orderByDescending = handRaisedParticipantsList.OrderByDescending(p => p.HandStatus.TimeStamp);
//foreach (var participant in handRaisedParticipantsList)
// Debug.Console(1, "handRaisedParticipantList: {0} | {1}", participant.UserName, participant.UserId);
}
List<ListParticipant> allOtherParticipantsList = participants.Where(p => !p.HandStatus.HandIsRaisedAndValid).ToList();
if (allOtherParticipantsList != null)
{
allOtherParticipantsList.OrderBy(p => p.UserName);
//foreach (var participant in allOtherParticipantsList)
// Debug.Console(1, "allOtherParticipantsList: {0} | {1}", participant.UserName, participant.UserId);
}
// merge the lists
List<ListParticipant> sortedList = handRaisedParticipantsList.Union(allOtherParticipantsList).ToList();
// return the sorted list
return sortedList;
}
} }
public class CallinCountryList public class CallinCountryList

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

@@ -0,0 +1,301 @@
using System;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges.JoinMaps;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
public class ZoomRoomJoinMap : VideoCodecControllerJoinMap
{
#region Digital
[JoinName("CanSwapContentWithThumbnail")]
public JoinDataComplete CanSwapContentWithThumbnail = new JoinDataComplete(
new JoinData
{
JoinNumber = 206,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates if content can be swapped with thumbnail",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SwapContentWithThumbnail")]
public JoinDataComplete SwapContentWithThumbnail = new JoinDataComplete(
new JoinData
{
JoinNumber = 206,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to swap content with thumbnail. FB reports current state",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("GetAvailableLayouts")]
public JoinDataComplete GetAvailableLayouts = new JoinDataComplete(
new JoinData
{
JoinNumber = 215,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Gets the available layouts. Will update the LayoutXXXXXIsAvailbale signals.",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("LayoutIsOnFirstPage")]
public JoinDataComplete LayoutIsOnFirstPage = new JoinDataComplete(
new JoinData
{
JoinNumber = 216,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Indicates if layout is on first page",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("LayoutIsOnLastPage")]
public JoinDataComplete LayoutIsOnLastPage = new JoinDataComplete(
new JoinData
{
JoinNumber = 217,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Indicates if layout is on first page",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("LayoutTurnToNextPage")]
public JoinDataComplete LayoutTurnToNextPage = new JoinDataComplete(
new JoinData
{
JoinNumber = 216,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Turns layout view to next page",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("LayoutTurnToPreviousPage")]
public JoinDataComplete LayoutTurnToPreviousPage = new JoinDataComplete(
new JoinData
{
JoinNumber = 217,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Turns layout view to previous page",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("LayoutGalleryIsAvailable")]
public JoinDataComplete LayoutGalleryIsAvailable = new JoinDataComplete(
new JoinData
{
JoinNumber = 221,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates if layout 'Gallery' is available",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.DigitalSerial
});
[JoinName("LayoutSpeakerIsAvailable")]
public JoinDataComplete LayoutSpeakerIsAvailable = new JoinDataComplete(
new JoinData
{
JoinNumber = 222,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates if layout 'Speaker' is available",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.DigitalSerial
});
[JoinName("LayoutStripIsAvailable")]
public JoinDataComplete LayoutStripIsAvailable = new JoinDataComplete(
new JoinData
{
JoinNumber = 223,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates if layout 'Strip' is available",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.DigitalSerial
});
[JoinName("LayoutShareAllIsAvailable")]
public JoinDataComplete LayoutShareAllIsAvailable = new JoinDataComplete(
new JoinData
{
JoinNumber = 224,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates if layout 'ShareAll' is available",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.DigitalSerial
});
// TODO: #714 [ ] JoinMap >> SelfivewPipSizeToggle
[JoinName("SelfviewPipSizeToggle")]
public JoinDataComplete SelfviewPipSizeToggle = new JoinDataComplete(
new JoinData
{
JoinNumber = 231,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Toggles the selfview pip size, (aka layout size)",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
//[JoinName("ParticipantAudioMuteToggleStart")]
//public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete(
// new JoinData
// {
// JoinNumber = 500,
// JoinSpan = 100
// },
// new JoinMetadata
// {
// Description = "Toggles the participant's audio mute status",
// JoinCapabilities = eJoinCapabilities.ToSIMPL,
// JoinType = eJoinType.Digital
// });
//[JoinName("ParticipantVideoMuteToggleStart")]
//public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete(
// new JoinData
// {
// JoinNumber = 800,
// JoinSpan = 100
// },
// new JoinMetadata
// {
// Description = "Toggles the participant's video mute status",
// JoinCapabilities = eJoinCapabilities.ToSIMPL,
// JoinType = eJoinType.Digital
// });
//[JoinName("ParticipantPinToggleStart")]
//public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete(
// new JoinData
// {
// JoinNumber = 1100,
// JoinSpan = 100
// },
// new JoinMetadata
// {
// Description = "Toggles the participant's pin status",
// JoinCapabilities = eJoinCapabilities.ToSIMPL,
// JoinType = eJoinType.Digital
// });
#endregion
#region Analog
[JoinName("NumberOfScreens")]
public JoinDataComplete NumberOfScreens = new JoinDataComplete(
new JoinData
{
JoinNumber = 11,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the number of screens connected",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("ScreenIndexToPinUserTo")]
public JoinDataComplete ScreenIndexToPinUserTo = new JoinDataComplete(
new JoinData
{
JoinNumber = 11,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Specifies the screen index a participant should be pinned to",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
#endregion
#region Serials
[JoinName("GetSetCurrentLayout")]
public JoinDataComplete GetSetCurrentLayout = new JoinDataComplete(
new JoinData
{
JoinNumber = 215,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Sets and reports the current layout. Use the LayoutXXXXIsAvailable signals to determine valid layouts",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
// TODO: #714 [ ] JoinMap >> GetSetSelfviewPipSize
[JoinName("GetSetSelfviewPipSize")]
public JoinDataComplete GetSetSelfviewPipSize = new JoinDataComplete(
new JoinData
{
JoinNumber = 230,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Sets and reports the selfview pip size, (aka layout size).",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.DigitalSerial
});
#endregion
public ZoomRoomJoinMap(uint joinStart)
: base(joinStart, typeof(ZoomRoomJoinMap))
{
}
public ZoomRoomJoinMap(uint joinStart, Type type)
: base(joinStart, type)
{
}
}
}

View File

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