Compare commits

...

35 Commits

Author SHA1 Message Date
Andrew Welker
10d77ac006 Merge pull request #1011 from PepperDash/hotfix/zoomroom-default-layout
Hotfix/zoomroom default layout
2022-10-06 11:06:30 -06:00
Neil Dorin
ca1cbb6e05 fix(essentials): Resolves null ref in LinkZoomRoomToApi 2022-09-29 14:11:41 -06:00
Neil Dorin
f82b7f8f12 refactor(essentials): cleans up some args names for clarity 2022-09-29 13:33:15 -06:00
Neil Dorin
dbd77f5f9f fix(essentials): Switch to SetSigTrueAction for a few joins 2022-09-29 12:35:05 -06:00
Neil Dorin
55031d16af docs(essentials): Add join name to printjoinmap and update description on StartMeetingNow join 2022-09-29 12:33:42 -06:00
Neil Dorin
4938071f70 fix(essentials): Updates the func to return whether sharing content 2022-09-29 11:22:13 -06:00
Neil Dorin
3670bde7cf fix(essentials): Adds extra private field to trigger OnShareInfoChanged 2022-09-29 10:53:55 -06:00
Neil Dorin
4deb9a0828 fix(essentials): Updates to deal with sharing status and adds a property to notify if meeting can be recorded 2022-09-28 14:55:14 -06:00
Neil Dorin
a524b1607d fix(essentials): Updates to deal with layouts and default layout for ZoomRoom 2022-09-28 12:28:37 -06:00
Andrew Welker
93435b60b5 Merge pull request #1005 from PepperDash/release/1.11.0
Release/1.11.0
2022-09-26 14:48:51 -06:00
Neil Dorin
2daf3c0328 Merge pull request #1004 from PepperDash/release/1.11.0
1.11.0
2022-09-26 14:13:50 -06:00
Andrew Welker
eaef8ea616 Merge branch 'main' into release/1.11.0 2022-09-26 11:52:43 -06:00
Andrew Welker
b67eb6325b Merge pull request #1003 from PepperDash/hotfix/add-zoomroom-share-info
Hotfix/add zoomroom share info
2022-09-26 08:40:36 -06:00
Andrew Welker
38cb86218c Merge branch 'development' into hotfix/add-zoomroom-share-info 2022-09-26 08:29:05 -06:00
Andrew Welker
edddf295fe Merge pull request #1002 from PepperDash/hotfix/add-zoomroom-share-info
Various Zoom Room updates
2022-09-23 14:53:22 -06:00
Neil Dorin
05ec0ebac3 fix(essentials): Adds ability to dial up to 10 calls from SIMPL bridge 2022-09-23 12:27:55 -06:00
Neil Dorin
c3d07fe4fd fix(essentials): Adds EndAllCalls to CancelJoinAttempt action 2022-09-23 08:28:32 -06:00
Neil Dorin
eae089cdf5 fix(essentials): updates to password prompt logic 2022-09-22 15:38:11 -06:00
Neil Dorin
b48859d202 adds missing .csproj update 2022-09-22 13:06:00 -06:00
Neil Dorin
bda46eb1b9 fix(essentials): adds cancel method for password prompt and adds wireless share instructions 2022-09-22 13:05:09 -06:00
Neil Dorin
ee735388bb fix(essentials): reworks SIMPL bridging logic for hiding password prompt 2022-09-15 12:44:17 -06:00
Andrew Welker
77f202b9f4 Merge pull request #1000 from PepperDash/hotfix/zoom-room-content-sharing-fb
fix(essentials): Fixes SharingSourceFeedback value to actually read F…
2022-09-14 17:00:09 -06:00
Neil Dorin
939afb7aae fix(essentials): Fixes SharingSourceFeedback value to actually read FB state instead of which on screen instructions are shown 2022-09-14 16:40:26 -06:00
Andrew Welker
4a98b58b60 Merge pull request #997 from PepperDash/hotfix/zoom-passcode-prompt
Update Zoom passcode bridging logic
2022-09-09 10:39:02 -06:00
Andrew Welker
2bf9336712 Merge branch 'main' into hotfix/zoom-passcode-prompt 2022-09-09 10:24:14 -06:00
Andrew Welker
c0c67f6c15 Merge pull request #996 from PepperDash/hotfix/zoom-room-privacy-mute-notincall
Hotfix/zoom room privacy mute notincall
2022-09-08 16:08:13 -06:00
Andrew Welker
eb3922aa43 Merge branch 'development' into hotfix/zoom-room-privacy-mute-notincall 2022-09-08 15:08:44 -06:00
Andrew Welker
598886dfd4 Merge pull request #995 from PepperDash/hotfix/zoom-room-privacy-mute-notincall
Set Zoom Room privacy/mic mute to report unmuted when not in a meeting
2022-09-08 15:08:32 -06:00
Neil Dorin
215cf6696e fix(essentials): Set not in call state to report as unmuted 2022-09-08 14:26:18 -06:00
Neil Dorin
c557400f38 fix(essentials): updates ZoomRoom mute state to report muted when not in call 2022-09-08 14:26:18 -06:00
Trevor Payne
49a96d2632 Merge pull request #993 from PepperDash/feature/Cisco-RoomOS-Codec-Support-Cleanup
Various fixes for VideoCodecBase
2022-09-06 17:36:06 -05:00
Trevor Payne
ccf7acd53d feat: update bridging, device factory, and interfaces
In order to support the way some Smart Objects work, a clear
directory join was needed in order to allow for clearing a
selection in certain circumstances.

In order to support finer-grained dependencies while
developing plugins, the Development Device Factory was added.
2022-09-06 17:16:27 -05:00
jdevito
f1590aeec8 fix: added 'CancelPasswordPrompt' join, updated linkToZoomApi 2022-09-06 14:10:21 -05:00
jdevito
f1d1ce9722 fix: added OnPasswordRequired event call in SubmitPassword method to clear popup when bridged 2022-09-06 14:04:19 -05:00
Andrew Welker
f5a352cf08 Merge pull request #990 from PepperDash/hotfix/essentials-cooling-routing
Magic Routing holds last requested route until cooling is complete
2022-09-02 11:37:46 -06:00
26 changed files with 931 additions and 423 deletions

View File

@@ -398,6 +398,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital
});
[JoinName("DirectoryEntryIsContact")]
public JoinDataComplete DirectoryEntryIsContact = new JoinDataComplete(
new JoinData
@@ -524,6 +525,21 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital
});
[JoinName("DirectoryClearSelected")]
public JoinDataComplete DirectoryClearSelected = new JoinDataComplete(
new JoinData
{
JoinNumber = 110,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Clear Selected Entry and String from Search",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraTiltUp")]
public JoinDataComplete CameraTiltUp = new JoinDataComplete(
new JoinData
@@ -776,44 +792,16 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital
});
[JoinName("DialMeeting1")]
public JoinDataComplete DialMeeting1 = new JoinDataComplete(
[JoinName("DialMeetingStart")]
public JoinDataComplete DialMeetingStart = new JoinDataComplete(
new JoinData
{
JoinNumber = 161,
JoinSpan = 1
JoinSpan = 10
},
new JoinMetadata
{
Description = "Join first meeting",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DialMeeting2")]
public JoinDataComplete DialMeeting2 = new JoinDataComplete(
new JoinData
{
JoinNumber = 162,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Join second meeting",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DialMeeting3")]
public JoinDataComplete DialMeeting3 = new JoinDataComplete(
new JoinData
{
JoinNumber = 163,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Join third meeting",
Description = "Join meeting",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
@@ -1256,11 +1244,12 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
},
new JoinMetadata
{
Description = "Directory Select Row",
Description = "Directory Select Row and Feedback",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("SelectedContactMethodCount")]
public JoinDataComplete SelectedContactMethodCount = new JoinDataComplete(
new JoinData
@@ -1289,6 +1278,22 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Analog
});
[JoinName("DirectorySelectRowFeedback")]
public JoinDataComplete DirectorySelectRowFeedback = new JoinDataComplete(
new JoinData
{
JoinNumber = 104,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Directory Select Row and Feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("CameraPresetSelect")]
public JoinDataComplete CameraPresetSelect = new JoinDataComplete(
new JoinData

View File

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

View File

@@ -131,4 +131,15 @@ namespace PepperDash.Essentials.Core
/// </summary>
public string MinimumEssentialsFrameworkVersion { get; protected set; }
}
public abstract class EssentialsPluginDevelopmentDeviceFactory<T> : EssentialsDeviceFactory<T>, IPluginDevelopmentDeviceFactory where T : EssentialsDevice
{
/// <summary>
/// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33")
/// </summary>
public string MinimumEssentialsFrameworkVersion { get; protected set; }
public List<string> DevelopmentEssentialsFrameworkVersions { get; protected set; }
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
public static class StringExtensions
{
public static string NullIfEmpty(this string s)
{
return string.IsNullOrEmpty(s) ? null : s;
}
public static string NullIfWhiteSpace(this string s)
{
return string.IsNullOrEmpty(s.Trim()) ? null : s;
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Globalization;
using Crestron.SimplSharp;
@@ -162,6 +163,38 @@ namespace PepperDash.Essentials.Core
AssemblyVersion = assemblyVersion;
}
public static bool IsRunningDevelopmentVersion(List<string> developmentVersions, string minimumVersion)
{
if (Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*").Groups[1].Value == "0")
{
Debug.Console(2, "Running Local Build. Bypassing Dependency Check.");
return true;
}
if (developmentVersions == null)
{
Debug.Console(0,
"Development Plugin does not specify a list of versions. Loading plugin may not work as expected. Checking Minumum version");
return IsRunningMinimumVersionOrHigher(minimumVersion);
}
Debug.Console(2, "Comparing running version '{0}' to minimum versions '{1}'", AssemblyVersion, developmentVersions);
var versionMatch = developmentVersions.FirstOrDefault(x => x == AssemblyVersion);
if (String.IsNullOrEmpty(versionMatch))
{
Debug.Console(0, "Essentials Build does not match any builds required for plugin load. Bypassing Plugin Load.");
return false;
}
Debug.Console(2, "Essentials Build {0} matches list of development builds", AssemblyVersion);
return IsRunningMinimumVersionOrHigher(minimumVersion);
}
/// <summary>
/// Checks to see if the running version meets or exceed the minimum specified version. For beta versions (0.xx.yy), will always return true.
/// </summary>

View File

@@ -283,9 +283,10 @@ namespace PepperDash.Essentials.Core
foreach (var join in joins)
{
Debug.Console(0,
@"Join Number: {0} | JoinSpan: '{1}' | Description: '{2}' | Type: '{3}' | Capabilities: '{4}'",
@"Join Number: {0} | JoinSpan: '{1}' | JoinName: {2} | Description: '{3}' | Type: '{4}' | Capabilities: '{5}'",
join.Value.JoinNumber,
join.Value.JoinSpan,
join.Key,
String.IsNullOrEmpty(join.Value.AttributeName) ? join.Value.Metadata.Label : join.Value.AttributeName,
join.Value.Metadata.JoinType.ToString(),
join.Value.Metadata.JoinCapabilities.ToString());

View File

@@ -218,6 +218,7 @@
<Compile Include="DeviceTypeInterfaces\IHasPhoneDialing.cs" />
<Compile Include="DeviceTypeInterfaces\IMobileControl.cs" />
<Compile Include="Extensions\JsonExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Factory\DeviceFactory.cs" />
<Compile Include="Factory\IDeviceFactory.cs" />
<Compile Include="Factory\ReadyEventArgs.cs" />

View File

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using PepperDash.Core;
@@ -15,5 +16,10 @@ namespace PepperDash.Essentials.Core
}
public interface IPluginDevelopmentDeviceFactory : IPluginDeviceFactory
{
List<string> DevelopmentEssentialsFrameworkVersions { get; }
}
}
}

View File

@@ -425,7 +425,11 @@ namespace PepperDash.Essentials
/// <param name="loadedAssembly"></param>
static void LoadCustomPlugin(IPluginDeviceFactory plugin, LoadedAssembly loadedAssembly)
{
var passed = Global.IsRunningMinimumVersionOrHigher(plugin.MinimumEssentialsFrameworkVersion);
var developmentPlugin = plugin as IPluginDevelopmentDeviceFactory;
var passed = developmentPlugin != null ? Global.IsRunningDevelopmentVersion
(developmentPlugin.DevelopmentEssentialsFrameworkVersions, developmentPlugin.MinimumEssentialsFrameworkVersion)
: Global.IsRunningMinimumVersionOrHigher(plugin.MinimumEssentialsFrameworkVersion);
if (!passed)
{

View File

@@ -49,6 +49,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
Stack<CodecDirectory> DirectoryBrowseHistoryStack { get; }
}
/// <summary>
///
/// </summary>

View File

@@ -211,7 +211,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
get
{
var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now
&& DateTime.Now <= EndTime.AddMinutes(-5);
&& DateTime.Now <= EndTime.AddSeconds(-_joinableCooldownSeconds);
//Debug.Console(2, "Meeting Id: {0} joinable: {1}", Id, joinable);
return joinable;
}
@@ -231,11 +231,23 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonIgnore]
public eMeetingEventChangeType NotifiedChangeTypes { get; set; }
[JsonIgnore] private readonly int _joinableCooldownSeconds;
public Meeting()
{
Calls = new List<Call>();
_joinableCooldownSeconds = 300;
}
public Meeting(int joinableCooldownSeconds)
{
Calls = new List<Call>();
_joinableCooldownSeconds = joinableCooldownSeconds;
}
#region Overrides of Object
public override string ToString()

View File

@@ -108,7 +108,7 @@
<Compile Include="Codec\eCodecCallStatus.cs" />
<Compile Include="Codec\eMeetingPrivacy.cs" />
<Compile Include="Codec\iCodecAudio.cs" />
<Compile Include="VideoCodec\IConvertiblePreset.cs" />
<Compile Include="VideoCodec\ConvertiblePreset.cs" />
<Compile Include="Codec\IHasCallHold.cs" />
<Compile Include="Codec\IHasDoNotDisturb.cs" />
<Compile Include="Codec\IHasExternalSourceSwitching.cs" />
@@ -185,6 +185,7 @@
<Compile Include="VideoCodec\MockVC\MockVC.cs" />
<Compile Include="VideoCodec\CiscoCodec\xStatus.cs" />
<Compile Include="VideoCodec\VideoCodecBase.cs" />
<Compile Include="VideoCodec\ZoomRoom\IZoomWirelessShareInstructions.cs" />
<Compile Include="VideoCodec\ZoomRoom\ResponseObjects.cs" />
<Compile Include="VideoCodec\ZoomRoom\ZoomRoom.cs" />
<Compile Include="VideoCodec\ZoomRoom\ZoomRoomCamera.cs" />

View File

@@ -377,5 +377,70 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
return meetings;
}
public static List<Meeting> GetGenericMeetingsFromBookingResult(List<Booking> bookings, int joinableCooldownSeconds)
{
var meetings = new List<Meeting>();
if (Debug.Level > 0)
{
Debug.Console(1, "Meetings List:\n");
}
foreach (Booking b in bookings)
{
var meeting = new Meeting(joinableCooldownSeconds);
if (b.Id != null)
meeting.Id = b.Id.Value;
if (b.Organizer != null)
meeting.Organizer = string.Format("{0}, {1}", b.Organizer.LastName.Value, b.Organizer.FirstName.Value);
if (b.Title != null)
meeting.Title = b.Title.Value;
if (b.Agenda != null)
meeting.Agenda = b.Agenda.Value;
if (b.Time != null)
{
meeting.StartTime = b.Time.StartTime.Value;
meeting.EndTime = b.Time.EndTime.Value;
}
if (b.Privacy != null)
meeting.Privacy = CodecCallPrivacy.ConvertToDirectionEnum(b.Privacy.Value);
//#warning Update this ConnectMode conversion after testing onsite. Expected value is "OBTP", but in PD NYC Test scenarios, "Manual" is being returned for OBTP meetings
if (b.DialInfo.ConnectMode != null)
if (b.DialInfo.ConnectMode.Value.ToLower() == "obtp" || b.DialInfo.ConnectMode.Value.ToLower() == "manual")
meeting.IsOneButtonToPushMeeting = true;
if (b.DialInfo.Calls.Call != null)
{
foreach (Call c in b.DialInfo.Calls.Call)
{
meeting.Calls.Add(new PepperDash.Essentials.Devices.Common.Codec.Call()
{
Number = c.Number.Value,
Protocol = c.Protocol.Value,
CallRate = c.CallRate.Value,
CallType = c.CallType.Value
});
}
}
meetings.Add(meeting);
if (Debug.Level > 0)
{
Debug.Console(1, "Title: {0}, ID: {1}, Organizer: {2}, Agenda: {3}", meeting.Title, meeting.Id, meeting.Organizer, meeting.Agenda);
Debug.Console(1, " Start Time: {0}, End Time: {1}, Duration: {2}", meeting.StartTime, meeting.EndTime, meeting.Duration);
Debug.Console(1, " Joinable: {0}\n", meeting.Joinable);
}
}
meetings.OrderBy(m => m.StartTime);
return meetings;
}
}
}

View File

@@ -24,7 +24,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
enum eCommandType { SessionStart, SessionEnd, Command, GetStatus, GetConfiguration };
public enum eExternalSourceType {camera, desktop, document_camera, mediaplayer, PC, whiteboard, other}
public enum eExternalSourceMode {Ready, NotReady, Hidden, Error}
public enum eExternalSourceMode {Ready, NotReady, Hidden, Error}
public class CiscoSparkCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory,
IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfView,
@@ -1023,7 +1023,7 @@ ConnectorID: {2}"
if (tempPresets.Count > 0)
{
// Create temporary list to store the existing items from the CiscoCodecStatus.RoomPreset collection
var existingRoomPresets = new List<IConvertiblePreset>();
var existingRoomPresets = new List<CiscoCodecStatus.RoomPreset>();
// Add the existing items to the temporary list
existingRoomPresets.AddRange(CodecStatus.Status.RoomPreset);
// Populate the CodecStatus object (this will append new values to the RoomPreset collection
@@ -1031,8 +1031,6 @@ ConnectorID: {2}"
var jResponse = JObject.Parse(response);
List<CiscoCodecStatus.RoomPreset> convertedRoomPresets =
existingRoomPresets.Select(a => (CiscoCodecStatus.RoomPreset) a).ToList();
IList<JToken> roomPresets = jResponse["Status"]["RoomPreset"].Children().ToList();
// Iterate the new items in this response agains the temporary list. Overwrite any existing items and add new ones.
@@ -1041,7 +1039,7 @@ ConnectorID: {2}"
var preset = camPreset as CiscoCodecStatus.RoomPreset;
if (preset == null) continue;
// First fine the existing preset that matches the id
var existingPreset = convertedRoomPresets.FirstOrDefault(p => p.id.Equals(preset.id));
var existingPreset = existingRoomPresets.FirstOrDefault(p => p.id.Equals(preset.id));
if (existingPreset != null)
{
Debug.Console(1, this, "Existing Room Preset with ID: {0} found. Updating.", existingPreset.id);
@@ -1073,7 +1071,7 @@ ConnectorID: {2}"
CodecStatus.Status.RoomPreset = existingRoomPresets;
// Generecise the list
NearEndPresets = existingRoomPresets.GetGenericPresets<CodecRoomPreset>();
NearEndPresets = existingRoomPresets.GetGenericPresets<CiscoCodecStatus.RoomPreset, CodecRoomPreset>();
var handler = CodecRoomPresetsListHasChanged;
if (handler != null)

View File

@@ -32,12 +32,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary>
/// <param name="presets"></param>
/// <returns></returns>
public static List<T> GetGenericPresets<T>(this List<IConvertiblePreset> presets)
public static List<TDestination> GetGenericPresets<TSource, TDestination>(this List<TSource> presets) where TSource : ConvertiblePreset where TDestination : PresetBase
{
return
presets.Select(preset => preset.ConvertCodecPreset())
.Where(newPreset => newPreset != null)
.Cast<T>()
.Cast<TDestination>()
.ToList();
}
}

View File

@@ -2186,7 +2186,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
}
public class RoomPreset : IConvertiblePreset
public class RoomPreset : ConvertiblePreset
{
public string id { get; set; }
public Defined Defined { get; set; }
@@ -2200,7 +2200,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
Type = new Type5();
}
public PresetBase ConvertCodecPreset()
public override PresetBase ConvertCodecPreset()
{
try
{
@@ -2240,7 +2240,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Proximity Proximity { get; set; }
public RoomAnalytics RoomAnalytics { get; set; }
public List<IConvertiblePreset> RoomPreset { get; set; }
public List<RoomPreset> RoomPreset { get; set; }
public SIP SIP { get; set; }
public Security Security { get; set; }
@@ -2257,7 +2257,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
Standby = new Standby();
Cameras = new Cameras();
RoomAnalytics = new RoomAnalytics();
RoomPreset = new List<IConvertiblePreset>();
RoomPreset = new List<RoomPreset>();
Conference = new Conference2();
SystemUnit = new SystemUnit();
Video = new Video();

View File

@@ -2,8 +2,8 @@
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
public interface IConvertiblePreset
public abstract class ConvertiblePreset
{
PresetBase ConvertCodecPreset();
public abstract PresetBase ConvertCodecPreset();
}
}

View File

@@ -22,25 +22,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
void MinMaxLayoutToggle();
}
/// <summary>
/// Defines the required elements for layout control with direct layout selection
/// </summary>
public interface IHasCodecLayoutsAvailable : IHasCodecLayouts
{
event EventHandler<AvailableLayoutChangedEventArgs> AvailableLayoutsChanged;
StringFeedback AvailableLocalLayoutsFeedback { get; }
List<CodecCommandWithLabel> AvailableLocalLayouts { get; }
void LocalLayoutSet(string layout);
void LocalLayoutSet(CodecCommandWithLabel layout);
}
public class AvailableLayoutChangedEventArgs : EventArgs
{
public List<CodecCommandWithLabel> AvailableLayouts { get; set; }
}
/// <summary>
/// Defines the requirements for Zoom Room layout control

View File

@@ -43,10 +43,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
[JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsLocked { get; private set; }
[JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsRecording { get; private set; }
public Boolean IsRecording { get; private set; }
[JsonProperty("canRecord", NullValueHandling = NullValueHandling.Ignore)]
public Boolean CanRecord { get; private set; }
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording)
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording, bool canRecord)
{
Id = id;
Name = name;
@@ -57,7 +59,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
IsSharingMeeting = isSharingMeeting;
WaitingForHost = waitingForHost;
IsLocked = isLocked;
IsRecording = isRecording;
IsRecording = isRecording;
CanRecord = CanRecord;
}
}

View File

@@ -3,9 +3,9 @@
public interface IHasPresentationOnlyMeeting
{
void StartSharingOnlyMeeting();
void StartSharingOnlyMeeting(eSharingMeetingMode mode);
void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration);
void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration, string password);
void StartSharingOnlyMeeting(eSharingMeetingMode displayMode);
void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration);
void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration, string password);
void StartNormalMeetingFromSharingOnlyMeeting();
}

View File

@@ -11,6 +11,7 @@ using PepperDash.Core;
using PepperDash.Core.Intersystem;
using PepperDash.Core.Intersystem.Tokens;
using PepperDash.Core.WebApi.Presets;
using Crestron.SimplSharp.Reflection;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
@@ -31,6 +32,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
private const int XSigEncoding = 28591;
protected const int MaxParticipants = 50;
private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs();
private IHasDirectory _directoryCodec;
private BasicTriList _directoryTrilist;
private VideoCodecControllerJoinMap _directoryJoinmap;
protected string _timeFormatSpecifier;
protected string _dateFormatSpecifier;
protected VideoCodecBase(DeviceConfig config)
: base(config)
{
@@ -214,6 +224,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
handler(this, new CodecCallStatusItemChangeEventArgs(item));
}
PrivacyModeIsOnFeedback.FireUpdate();
if (AutoShareContentWhileInCall)
{
StartSharing();
@@ -371,10 +383,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
LinkVideoCodecCameraLayoutsToApi(codec as IHasCodecLayouts, trilist, joinMap);
}
if (codec is IHasCodecLayoutsAvailable)
{
LinkVideoCodecAvailableLayoutsToApi(codec as IHasCodecLayoutsAvailable, trilist, joinMap);
}
if (codec is IHasSelfviewPosition)
{
@@ -692,37 +700,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
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
// );
// 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
@@ -789,10 +797,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetSigFalseAction(joinMap.SourceShareStart.JoinNumber, StartSharing);
trilist.SetSigFalseAction(joinMap.SourceShareEnd.JoinNumber, StopSharing);
trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, (b) => AutoShareContentWhileInCall = b);
trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, b => AutoShareContentWhileInCall = b);
}
private List<Meeting> _currentMeetings = new List<Meeting>();
private List<Meeting> _currentMeetings = new List<Meeting>();
private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
@@ -800,38 +808,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetUShortSigAction(joinMap.MinutesBeforeMeetingStart.JoinNumber, (i) =>
{
codec.CodecSchedule.MeetingWarningMinutes = i;
codec.CodecSchedule.MeetingWarningMinutes = i;
});
trilist.SetSigFalseAction(joinMap.DialMeeting1.JoinNumber, () =>
{
var mtg = 1;
var index = mtg - 1;
Debug.Console(1, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}",
mtg, joinMap.DialMeeting1.JoinNumber, index, _currentMeetings[index].Id, _currentMeetings[index].Title);
if (_currentMeetings[index] != null)
Dial(_currentMeetings[index]);
});
trilist.SetSigFalseAction(joinMap.DialMeeting2.JoinNumber, () =>
{
var mtg = 2;
var index = mtg - 1;
Debug.Console(1, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}",
mtg, joinMap.DialMeeting2.JoinNumber, index, _currentMeetings[index].Id, _currentMeetings[index].Title);
if (_currentMeetings[index] != null)
Dial(_currentMeetings[index]);
});
trilist.SetSigFalseAction(joinMap.DialMeeting3.JoinNumber, () =>
{
var mtg = 3;
var index = mtg - 1;
Debug.Console(1, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}",
mtg, joinMap.DialMeeting3.JoinNumber, index, _currentMeetings[index].Id, _currentMeetings[index].Title);
if (_currentMeetings[index] != null)
Dial(_currentMeetings[index]);
});
for (uint i = 0; i < joinMap.DialMeetingStart.JoinSpan; i++)
{
Debug.Console(1, this, "Setting action to Dial Meeting {0} to digital join {1}", i + 1, joinMap.DialMeetingStart.JoinNumber + i);
var joinNumber = joinMap.DialMeetingStart.JoinNumber + i;
var mtg = i + 1;
var index = (int)i;
trilist.SetSigFalseAction(joinNumber, () =>
{
Debug.Console(1, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}",
mtg, joinMap.DialMeetingStart.JoinNumber + i, index, _currentMeetings[index].Id, _currentMeetings[index].Title);
if (_currentMeetings[index] != null)
Dial(_currentMeetings[index]);
});
}
codec.CodecSchedule.MeetingsListHasChanged += (sender, args) => UpdateMeetingsList(codec, trilist, joinMap);
codec.CodecSchedule.MeetingEventChange += (sender, args) =>
@@ -842,7 +837,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
}
};
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
trilist.SetUShortSigAction(joinMap.MeetingsToDisplay.JoinNumber, m => MeetingsToDisplay = m);
MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]);
@@ -904,90 +898,90 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
public IntFeedback MeetingsToDisplayFeedback { get; set; }
private string UpdateMeetingsListXSig(List<Meeting> meetings)
{
private string UpdateMeetingsListXSig(List<Meeting> meetings)
{
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
//const int _meetingsToDisplay = 3;
const int maxDigitals = 2;
const int maxStrings = 7;
const int offset = maxDigitals + maxStrings;
var digitalIndex = maxStrings * _meetingsToDisplay; //15
var stringIndex = 0;
var meetingIndex = 0;
const int maxDigitals = 2;
const int maxStrings = 7;
const int offset = maxDigitals + maxStrings;
var digitalIndex = maxStrings * _meetingsToDisplay; //15
var stringIndex = 0;
var meetingIndex = 0;
var tokenArray = new XSigToken[_meetingsToDisplay * offset];
/*
* Digitals
* IsJoinable - 1
* IsDialable - 2
*
* Serials
* Organizer - 1
* Title - 2
* Start Date - 3
* Start Time - 4
* End Date - 5
* End Time - 6
* Id - 7
*/
var tokenArray = new XSigToken[_meetingsToDisplay * offset];
/*
* Digitals
* IsJoinable - 1
* IsDialable - 2
*
* Serials
* Organizer - 1
* Title - 2
* Start Date - 3
* Start Time - 4
* End Date - 5
* End Time - 6
* Id - 7
*/
foreach (var meeting in meetings)
{
var currentTime = DateTime.Now;
foreach (var meeting in meetings)
{
var currentTime = DateTime.Now;
if (meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue;
if (meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue;
if (meetingIndex >= _meetingsToDisplay * offset)
{
Debug.Console(2, this, "Max Meetings reached");
break;
}
if (meetingIndex >= _meetingsToDisplay * offset)
{
Debug.Console(2, this, "Max Meetings reached");
break;
}
//digitals
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Id != "0");
//digitals
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Id != "0");
//serials
tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer);
tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title);
tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture));
tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture));
tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture));
tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture));
tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id);
//serials
tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer);
tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title);
tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString("t", Global.Culture));
tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString("t", Global.Culture));
tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString("t", Global.Culture));
tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString("t", Global.Culture));
tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id);
digitalIndex += maxDigitals;
meetingIndex += offset;
stringIndex += maxStrings;
}
while (meetingIndex < _meetingsToDisplay * offset)
{
Debug.Console(2, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}",
meetingIndex, _meetingsToDisplay * offset);
digitalIndex += maxDigitals;
meetingIndex += offset;
stringIndex += maxStrings;
}
//digitals
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false);
while (meetingIndex < _meetingsToDisplay * offset)
{
Debug.Console(2, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}",
meetingIndex, _meetingsToDisplay * offset);
//serials
tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty);
tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty);
tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty);
tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty);
tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty);
tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty);
tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty);
//digitals
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false);
digitalIndex += maxDigitals;
meetingIndex += offset;
stringIndex += maxStrings;
}
//serials
tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty);
tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty);
tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty);
tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty);
tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty);
tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty);
tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty);
return GetXSigString(tokenArray);
}
digitalIndex += maxDigitals;
meetingIndex += offset;
stringIndex += maxStrings;
}
return GetXSigString(tokenArray);
}
private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
@@ -998,7 +992,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i, trilist, joinMap));
// Report feedback for number of contact methods for selected contact
//Special Change for protected directory clear
trilist.SetBoolSigAction(joinMap.DirectoryClearSelected.JoinNumber, (b) => SelectDirectoryEntry(_directoryCodec, 0, _directoryTrilist, _directoryJoinmap));
// Report feedback for number of contact methods for selected contact
trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot);
@@ -1012,7 +1010,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot,
codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
@@ -1027,32 +1026,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(args.Directory, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
var directoryXSig = UpdateDirectoryXSig(args.Directory,
codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
};
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
var clearBytes = XSigHelpers.ClearOutputs();
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
var clearBytes = XSigHelpers.ClearOutputs();
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false);
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
};
}
private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
if (i < 1 || i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return;
if (i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return;
_selectedDirectoryItem = i == 0 ? null : codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1];
trilist.SetUshort(joinMap.DirectorySelectRowFeedback.JoinNumber, i);
_selectedDirectoryItem = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1];
if (_selectedDirectoryItem == null) trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false);
if (_selectedDirectoryItem is DirectoryFolder)
@@ -1064,6 +1063,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber);
trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false);
return;
}
@@ -1071,13 +1071,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty);
var selectedContact = _selectedDirectoryItem as DirectoryContact;
if (selectedContact != null)
{
trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, selectedContact.Name);
}
// Allow auto dial of selected line. Always dials first contact method
if (selectedContact != null && selectedContact.ContactMethods.Count >= 1)
{
trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, true);
}
trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber,
selectedContact != null ? selectedContact.Name : string.Empty);
// Allow auto dial of selected line. Always dials first contact method
if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber))
{
var invitableEntry = _selectedDirectoryItem as IInvitableContact;
@@ -1090,12 +1093,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
var entryToDial = _selectedDirectoryItem as DirectoryContact;
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, selectedContact.ContactMethods[0].Number);
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber,
selectedContact != null ? selectedContact.ContactMethods[0].Number : string.Empty);
if (entryToDial == null) return;
Dial(entryToDial.ContactMethods[0].Number);
return;
}
else
{
@@ -1181,50 +1184,49 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
return GetXSigString(tokenArray);
}
private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot)
{
var xSigMaxIndex = 1023;
var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex
? xSigMaxIndex
: directory.CurrentDirectoryResults.Count];
private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot)
{
var xSigMaxIndex = 1023;
var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count > xSigMaxIndex
? xSigMaxIndex
: directory.CurrentDirectoryResults.Count];
Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot, directory.CurrentDirectoryResults.Count, tokenArray.Length);
Debug.Console(2, this, "IsRoot: {0}, Directory Count: {1}, TokenArray.Length: {2}", isRoot,
directory.CurrentDirectoryResults.Count, tokenArray.Length);
var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex
? directory.CurrentDirectoryResults.Take(xSigMaxIndex)
: directory.CurrentDirectoryResults;
var contactsToDisplay = isRoot
? contacts.Where(c => c.ParentFolderId == "root")
: contacts.Where(c => c.ParentFolderId != "root");
var contacts = directory.CurrentDirectoryResults.Count > xSigMaxIndex
? directory.CurrentDirectoryResults.Take(xSigMaxIndex)
: directory.CurrentDirectoryResults;
var counterIndex = 1;
foreach (var entry in contactsToDisplay)
{
var arrayIndex = counterIndex - 1;
var entryIndex = counterIndex;
var counterIndex = 1;
foreach (var entry in contacts)
{
var arrayIndex = counterIndex - 1;
var entryIndex = counterIndex;
Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}, Type: {3}, ParentFolderId: {4}",
entry.Name, entry.FolderId, entryIndex, entry.GetType().GetCType().FullName, entry.ParentFolderId);
Debug.Console(2, this, "Entry{2:0000} Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId, entryIndex);
if (entry is DirectoryFolder)
{
tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name));
if (entry is DirectoryFolder && entry.ParentFolderId == "root")
{
tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, String.Format("[+] {0}", entry.Name));
counterIndex++;
counterIndex++;
counterIndex++;
continue;
}
continue;
}
tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name);
counterIndex++;
}
return GetXSigString(tokenArray);
tokenArray[arrayIndex] = new XSigSerialToken(entryIndex, entry.Name);
counterIndex++;
}
return GetXSigString(tokenArray);
}
private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
trilist.SetSigFalseAction(joinMap.ManualDial.JoinNumber,
() => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue));
@@ -1489,14 +1491,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentLayoutStringFb.JoinNumber]);
}
private void LinkVideoCodecAvailableLayoutsToApi(IHasCodecLayoutsAvailable codec, BasicTriList trilist,
VideoCodecControllerJoinMap joinMap)
{
codec.AvailableLocalLayoutsFeedback.LinkInputSig(trilist.StringInput[joinMap.AvailableLayoutsFb.JoinNumber]);
trilist.SetStringSigAction(joinMap.SelectLayout.JoinNumber, codec.LocalLayoutSet);
}
private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
trilist.SetSigFalseAction(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeOn);
@@ -2023,4 +2017,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
public class ShareInfoEventArgs : EventArgs
{
public zStatus.Sharing SharingStatus { get; private set; }
public ShareInfoEventArgs(zStatus.Sharing status)
{
SharingStatus = status;
}
}
public interface IZoomWirelessShareInstructions
{
event EventHandler<ShareInfoEventArgs> ShareInfoChanged;
zStatus.Sharing SharingState { get; }
}
}

View File

@@ -434,13 +434,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public bool supports_Web_Settings_Push { get; set; }
}
public enum eDisplayState
{
None,
Laptop,
IOS,
}
public class Sharing : NotifiableObject
{
private string _dispState;
private eDisplayState _dispState;
private string _password;
private bool _isAirHostClientConnected;
private bool _isSharingBlackMagic;
private bool _isDirectPresentationConnected;
private bool _isBlackMagicConnected;
public string directPresentationPairingCode { get; set; }
@@ -448,7 +456,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// Laptop client sharing key
/// </summary>
public string directPresentationSharingKey { get; set; }
public string dispState
public eDisplayState dispState
{
get
{
@@ -477,7 +485,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
public bool isBlackMagicConnected { get; set; }
public bool isBlackMagicConnected
{
get { return _isBlackMagicConnected; }
set
{
if (value != _isBlackMagicConnected)
{
_isBlackMagicConnected = value;
NotifyPropertyChanged("isBlackMagicConnected");
}
}
}
public bool isBlackMagicDataAvailable { get; set; }
public bool isDirectPresentationConnected
@@ -506,8 +525,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
/// <summary>
/// IOS Airplay code
/// </summary>
@@ -622,6 +639,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// backer variables
private bool _can_Switch_Speaker_View;
private bool _can_Switch_Wall_View;
private bool _can_Switch_Strip_View;
private bool _can_Switch_Share_On_All_Screens;
private bool _can_Switch_Floating_Share_Content;
private bool _is_In_First_Page;
@@ -709,6 +727,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
[JsonProperty("can_Switch_Strip_View")]
public bool can_Switch_Strip_View
{
get
{
return _can_Switch_Strip_View;
}
set
{
if (value != _can_Switch_Strip_View)
{
_can_Switch_Strip_View = value;
NotifyPropertyChanged("can_Switch_Strip_View");
}
}
}
[JsonProperty("is_In_First_Page")]
public bool is_In_First_Page
{
@@ -770,11 +805,43 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public class CallRecordInfo : NotifiableObject
{
private bool _meetingIsBeingRecorded;
private bool _canRecord;
private bool _emailRequired;
public bool canRecord { get; set; }
public bool emailRequired { get; set; }
public bool amIRecording { get; set; }
public bool canRecord
{
get
{
return _canRecord;
}
set
{
if (value != _canRecord)
{
_canRecord = value;
NotifyPropertyChanged("canRecord");
}
}
}
public bool emailRequired
{
get
{
return _emailRequired;
}
set
{
if (value != _emailRequired)
{
_emailRequired = value;
NotifyPropertyChanged("emailRequired");
}
}
}
public bool meetingIsBeingRecorded
{
get
@@ -793,6 +860,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
/// <summary>
/// Indicates if recording is allowed (when meeting capable and and email is not required to be entered by the user)
/// </summary>
public bool AllowRecord
{
get
{
return canRecord && !emailRequired;
}
}
public CallRecordInfo()
{
Debug.Console(2, Debug.ErrorLogLevel.Notice, "********************************************* CallRecordInfo() ******************************************");

View File

@@ -27,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMuteWithUnmuteReqeust, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting,
IHasMeetingLock, IHasMeetingRecordingWithPrompt
IHasMeetingLock, IHasMeetingRecordingWithPrompt, IZoomWirelessShareInstructions
{
public event EventHandler VideoUnmuteRequested;
@@ -47,12 +47,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A";
private string[] Delimiters = new string[] { EchoDelimiter, JsonDelimiter, "OK\x0D\x0A", "end\x0D\x0A" };
//"echo off\x0D\x0A\x0A\x0D\x0A"
private readonly GenericQueue _receiveQueue;
//private readonly CrestronQueue<string> _receiveQueue;
//private readonly Thread _receiveThread;
private readonly ZoomRoomSyncState _syncState;
public bool CommDebuggingIsOn;
@@ -64,6 +59,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private CameraBase _selectedCamera;
private string _lastDialedMeetingNumber;
private readonly ZoomRoomPropertiesConfig _props;
public ZoomRoom(DeviceConfig config, IBasicCommunication comm)
@@ -214,7 +210,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
protected override Func<bool> PrivacyModeIsOnFeedbackFunc
{
get { return () => Configuration.Call.Microphone.Mute; }
get
{
return () =>
{
//Debug.Console(2, this, "PrivacyModeIsOnFeedbackFunc. IsInCall: {0} muteState: {1}", IsInCall, Configuration.Call.Microphone.Mute);
if (IsInCall)
{
//Debug.Console(2, this, "reporting muteState: ", Configuration.Call.Microphone.Mute);
return Configuration.Call.Microphone.Mute;
}
else
{
//Debug.Console(2, this, "muteState: true", IsInCall);
return false;
}
};
}
}
protected override Func<bool> StandbyIsOnFeedbackFunc
@@ -224,12 +236,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
protected override Func<string> SharingSourceFeedbackFunc
{
get { return () => Status.Sharing.dispState; }
get
{
return () =>
{
if (Status.Sharing.isAirHostClientConnected)
return "Airplay";
else if (Status.Sharing.isDirectPresentationConnected || Status.Sharing.isBlackMagicConnected)
return "Laptop";
else return "None";
};
}
}
protected override Func<bool> SharingContentIsOnFeedbackFunc
{
get { return () => Status.Call.Sharing.IsSharing; }
get { return () => Status.Sharing.isAirHostClientConnected || Status.Sharing.isDirectPresentationConnected || Status.Sharing.isSharingBlackMagic; }
}
protected Func<bool> FarEndIsSharingContentFeedbackFunc
@@ -506,6 +529,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// </summary>
private void SetUpCallFeedbackActions()
{
Status.Sharing.PropertyChanged -= HandleSharingStateUpdate;
Status.Sharing.PropertyChanged += HandleSharingStateUpdate;
Status.Call.Sharing.PropertyChanged -= HandleSharingStateUpdate;
Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate;
@@ -518,7 +544,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void HandleCallRecordInfoStateUpdate(object sender, PropertyChangedEventArgs a)
{
if (a.PropertyName == "meetingIsBeingRecorded")
if (a.PropertyName == "meetingIsBeingRecorded" || a.PropertyName == "emailRequired" || a.PropertyName == "canRecord")
{
MeetingIsRecordingFeedback.FireUpdate();
@@ -531,7 +557,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord);
MeetingInfo = meetingInfo;
}
}
@@ -557,10 +583,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a)
{
if (a.PropertyName != "State")
{
return;
}
//if (a.PropertyName != "State")
//{
// return;
//}
SharingContentIsOnFeedback.FireUpdate();
ReceivingContent.FireUpdate();
@@ -570,21 +596,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// Update the share status of the meeting info
if (MeetingInfo == null)
{
var sharingStatus = GetSharingStatus();
MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = new MeetingInfo("", "", "", "", GetSharingStatus(), GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord);
return;
}
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None",
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord);
MeetingInfo = meetingInfo;
}
catch (Exception e)
{
Debug.Console(1, this, "Error processing state property update. {0}", e.Message);
Debug.Console(2, this, e.StackTrace);
MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, false);
}
}
@@ -691,7 +715,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue
MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord
);
}
};
@@ -727,15 +751,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Status.Sharing.PropertyChanged += (o, a) =>
{
OnShareInfoChanged(Status.Sharing);
SharingSourceFeedback.FireUpdate();
switch (a.PropertyName)
{
case "dispState":
SharingSourceFeedback.FireUpdate();
break;
case "password":
break;
case "isAirHostClientConnected":
case "isDirectPresentationConnected":
case "isSharingBlackMagic":
{
Debug.Console(2, this, "Updating sharing status: {0}", a.PropertyName);
@@ -756,7 +777,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord);
MeetingInfo = meetingInfo;
break;
}
@@ -790,8 +811,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Debug.Console(1, this, "Status.Layout.PropertyChanged a.PropertyName: {0}", a.PropertyName);
switch (a.PropertyName.ToLower())
{
case "can_switch_speaker_view":
case "can_Switch_speaker_view":
case "can_switch_wall_view":
case "can_switch_strip_view":
case "video_type":
case "can_switch_share_on_all_screens":
{
ComputeAvailableLayouts();
@@ -807,7 +830,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
LayoutViewIsOnLastPageFeedback.FireUpdate();
break;
}
case "can_Switch_Floating_Share_Content":
case "can_switch_floating_share_content":
{
CanSwapContentWithThumbnailFeedback.FireUpdate();
break;
@@ -1448,13 +1471,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingInfo.Id,
MeetingInfo.Name,
Participants.Host.Name,
MeetingInfo.Password,
MeetingInfo.ShareStatus,
MeetingInfo.Password,
GetSharingStatus(),
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingIsRecordingFeedback.BoolValue,
Status.Call.CallRecordInfo.AllowRecord
);
MeetingInfo = meetingInfo;
PrintCurrentCallParticipants();
@@ -1539,7 +1564,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing);
SetLayout();
SetDefaultLayout();
break;
}
@@ -1669,14 +1694,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (MeetingInfo == null)
{
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord);
UpdateCallStatus();
break;
}
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord);
UpdateCallStatus();
@@ -1686,12 +1711,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (MeetingInfo == null)
{
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord);
break;
}
MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password,
GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord);
break;
}
@@ -1781,7 +1806,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (result.Success)
{
MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = new MeetingInfo("", "", "", "", GetSharingStatus(), true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord);
break;
}
@@ -1915,7 +1940,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
private void SetLayout()
private void SetDefaultLayout()
{
if (!_props.AutoDefaultLayouts) return;
@@ -1928,8 +1953,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
else
{
SendText(String.Format("zconfiguration call layout style: {0}",
_props.DefaultCallLayout));
if (_props.DefaultCallLayout == (_props.DefaultCallLayout & AvailableLayouts))
{
SendText(String.Format("zconfiguration call layout style: {0}",
_props.DefaultCallLayout));
}
else
Debug.Console(0, this, "Unable to set default Layout. {0} not currently an available layout based on meeting state", _props.DefaultCallLayout);
}
}
@@ -2127,10 +2157,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
!String.Equals(Status.Call.Info.meeting_type,"NORMAL"),
false,
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue
MeetingIsRecordingFeedback.BoolValue, Status.Call.CallRecordInfo.AllowRecord
);
SetDefaultLayout();
}
// TODO [ ] Issue #868
else if (item.Status == eCodecCallStatus.Disconnected)
{
MeetingInfo = new MeetingInfo(
@@ -2143,7 +2175,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
false,
false,
false,
false
false, Status.Call.CallRecordInfo.AllowRecord
);
}
@@ -2151,11 +2183,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Debug.Console(1, this, "[OnCallStatusChange] Current Call Status: {0}",
Status.Call != null ? Status.Call.Status.ToString() : "no call");
if (_props.AutoDefaultLayouts)
{
SetLayout();
}
}
private string GetSharingStatus()
@@ -2223,6 +2250,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
/// <summary>
/// Starts sharing HDMI source
/// </summary>
public override void StartSharing()
{
SendText("zCommand Call Sharing HDMI Start");
@@ -2368,6 +2398,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <param name="joinMap"></param>
public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap)
{
var meetingInfoCodec = this as IHasMeetingInfo;
if (meetingInfoCodec != null)
{
if (meetingInfoCodec.MeetingInfo != null)
{
trilist.SetBool(joinMap.MeetingCanRecord.JoinNumber, meetingInfoCodec.MeetingInfo.CanRecord);
}
meetingInfoCodec.MeetingInfoChanged += (o, a) =>
{
trilist.SetBool(joinMap.MeetingCanRecord.JoinNumber, a.Info.CanRecord);
};
}
var recordingCodec = this as IHasMeetingRecordingWithPrompt;
if (recordingCodec != null)
{
@@ -2482,24 +2526,34 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
//trilist.SetString(joinMap.CurrentSource.JoinNumber, args.Info.ShareStatus);
};
trilist.SetSigTrueAction(joinMap.StartMeetingNow.JoinNumber, () => StartMeeting(0));
trilist.SetSigTrueAction(joinMap.ShareOnlyMeeting.JoinNumber, StartSharingOnlyMeeting);
trilist.SetSigTrueAction(joinMap.StartNormalMeetingFromSharingOnlyMeeting.JoinNumber, StartNormalMeetingFromSharingOnlyMeeting);
// not sure if this would be needed here, should be handled by VideoCodecBase.cs LinkToApi methods
//DirectoryResultReturned += (device, args) =>
//{
// // add logic here if necessary when event fires
//};
trilist.SetSigFalseAction(joinMap.StartMeetingNow.JoinNumber, () => StartMeeting(0));
trilist.SetSigFalseAction(joinMap.ShareOnlyMeeting.JoinNumber, StartSharingOnlyMeeting);
trilist.SetSigFalseAction(joinMap.StartNormalMeetingFromSharingOnlyMeeting.JoinNumber, StartNormalMeetingFromSharingOnlyMeeting);
trilist.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword);
// Subscribe to call status to clear ShowPasswordPrompt when in meeting
this.CallStatusChange += (o, a) =>
{
if (a.CallItem.Status == eCodecCallStatus.Connected || a.CallItem.Status == eCodecCallStatus.Disconnected)
{
trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false);
}
};
trilist.SetSigFalseAction(joinMap.CancelJoinAttempt.JoinNumber, () => {
trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false);
EndAllCalls();
});
PasswordRequired += (devices, args) =>
{
Debug.Console(0, this, "***********************************PaswordRequired. Message: {0} Cancelled: {1} Last Incorrect: {2} Failed: {3}", args.Message, args.LoginAttemptCancelled, args.LastAttemptWasIncorrect, args.LoginAttemptFailed);
if (args.LoginAttemptCancelled)
{
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false);
trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, false);
return;
}
@@ -2515,7 +2569,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
trilist.SetBool(joinMap.PasswordIncorrect.JoinNumber, args.LastAttemptWasIncorrect);
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, true);
trilist.SetBool(joinMap.MeetingPasswordRequired.JoinNumber, true);
};
trilist.OnlineStatusChange += (device, args) =>
@@ -2531,8 +2585,34 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
pinCodec.NumberOfScreensFeedback.FireUpdate();
layoutSizeCodec.SelfviewPipSizeFeedback.FireUpdate();
};
var wirelessInfoCodec = this as IZoomWirelessShareInstructions;
if (wirelessInfoCodec != null)
{
if (Status != null && Status.Sharing != null)
{
SetSharingStateJoins(Status.Sharing, trilist, joinMap);
}
wirelessInfoCodec.ShareInfoChanged += (o, a) =>
{
SetSharingStateJoins(a.SharingStatus, trilist, joinMap);
};
}
}
void SetSharingStateJoins(zStatus.Sharing state, BasicTriList trilist, ZoomRoomJoinMap joinMap)
{
trilist.SetBool(joinMap.IsSharingAirplay.JoinNumber, state.isAirHostClientConnected);
trilist.SetBool(joinMap.IsSharingHdmi.JoinNumber, state.isBlackMagicConnected || state.isDirectPresentationConnected);
trilist.SetString(joinMap.DisplayState.JoinNumber, state.dispState.ToString());
trilist.SetString(joinMap.AirplayShareCode.JoinNumber, state.password);
trilist.SetString(joinMap.LaptopShareKey.JoinNumber, state.directPresentationSharingKey);
trilist.SetString(joinMap.WifiName.JoinNumber, state.wifiName);
trilist.SetString(joinMap.ServerName.JoinNumber, state.serverName);
}
public override void ExecuteSwitch(object selector)
{
var action = selector as Action;
@@ -3209,7 +3289,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// There is no property that directly reports if strip mode is valid, but API stipulates
// that strip mode is available if the number of screens is 1
if (Status.NumberOfScreens.NumOfScreens == 1)
if (Status.NumberOfScreens.NumOfScreens == 1 || Status.Layout.can_Switch_Strip_View || Status.Layout.video_type.ToLower() == "strip")
{
availableLayouts |= zConfiguration.eLayoutStyle.Strip;
}
@@ -3224,10 +3304,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var handler = LayoutInfoChanged;
if (handler != null)
{
var currentLayout = zConfiguration.eLayoutStyle.None;
currentLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle), string.IsNullOrEmpty(LocalLayoutFeedback.StringValue) ? "None" : LocalLayoutFeedback.StringValue, true);
handler(this, new LayoutInfoChangedEventArgs()
{
AvailableLayouts = AvailableLayouts,
CurrentSelectedLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle),string.IsNullOrEmpty(LocalLayoutFeedback.StringValue) ? "None" : LocalLayoutFeedback.StringValue , true),
CurrentSelectedLayout = currentLayout,
LayoutViewIsOnFirstPage = LayoutViewIsOnFirstPageFeedback.BoolValue,
LayoutViewIsOnLastPage = LayoutViewIsOnLastPageFeedback.BoolValue,
CanSwapContentWithThumbnail = CanSwapContentWithThumbnailFeedback.BoolValue,
@@ -3357,6 +3442,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
Debug.Console(2, this, "Password Submitted: {0}", password);
Dial(_lastDialedMeetingNumber, password);
//OnPasswordRequired(false, false, true, "");
}
void OnPasswordRequired(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message)
@@ -3403,19 +3489,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
StartSharingOnlyMeeting(eSharingMeetingMode.None, 30, String.Empty);
}
public void StartSharingOnlyMeeting(eSharingMeetingMode mode)
public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode)
{
StartSharingOnlyMeeting(mode, 30, String.Empty);
StartSharingOnlyMeeting(displayMode, DefaultMeetingDurationMin, String.Empty);
}
public void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration)
public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration)
{
StartSharingOnlyMeeting(mode, duration, String.Empty);
StartSharingOnlyMeeting(displayMode, duration, String.Empty);
}
public void StartSharingOnlyMeeting(eSharingMeetingMode mode, ushort duration, string password)
public void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration, string password)
{
SendText(String.Format("zCommand Dial Sharing Duration: {0} DisplayState: {1} Password: {2}", duration, mode, password));
SendText(String.Format("zCommand Dial Sharing Duration: {0} DisplayState: {1} Password: {2}", duration, displayMode, password));
}
public void StartNormalMeetingFromSharingOnlyMeeting()
@@ -3492,6 +3578,41 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
#endregion
#region IZoomWirelessShareInstructions Members
public event EventHandler<ShareInfoEventArgs> ShareInfoChanged;
public zStatus.Sharing SharingState
{
get
{
return Status.Sharing;
}
}
void OnShareInfoChanged(zStatus.Sharing status)
{
Debug.Console(2, this,
@"ShareInfoChanged:
isSharingHDMI: {0}
isSharingAirplay: {1}
AirplayPassword: {2}
OSD Display State: {3}
",
status.isSharingBlackMagic,
status.isAirHostClientConnected,
status.password,
status.dispState);
var handler = ShareInfoChanged;
if (handler != null)
{
handler(this, new ShareInfoEventArgs(status));
}
}
#endregion
}
/// <summary>

View File

@@ -8,9 +8,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
#region Digital
// TODO [ ] Issue #868
[JoinName("ShowPasswordPrompt")]
public JoinDataComplete ShowPasswordPrompt = new JoinDataComplete(
[JoinName("CancelJoinAttempt")]
public JoinDataComplete CancelJoinAttempt = new JoinDataComplete(
new JoinData
{
JoinNumber = 5,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to hide the password prompt",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("MeetingPasswordRequired")]
public JoinDataComplete MeetingPasswordRequired = new JoinDataComplete(
new JoinData
{
JoinNumber = 6,
@@ -23,7 +36,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("PasswordIncorrect")]
public JoinDataComplete PasswordIncorrect = new JoinDataComplete(
new JoinData
@@ -38,8 +50,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("PassowrdLoginFailed")]
[JoinName("PasswordLoginFailed")]
public JoinDataComplete PasswordLoginFailed = new JoinDataComplete(
new JoinData
{
@@ -53,7 +64,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("WaitingForHost")]
public JoinDataComplete WaitingForHost = new JoinDataComplete(
new JoinData
@@ -68,7 +78,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("IsHost")]
public JoinDataComplete IsHost = new JoinDataComplete(
new JoinData
@@ -83,7 +92,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("StartMeetingNow")]
public JoinDataComplete StartMeetingNow = new JoinDataComplete(
new JoinData
@@ -93,12 +101,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
},
new JoinMetadata
{
Description = "FB Indicates the password prompt is active",
Description = "Pulse to start an ad-hoc meeting with the default duration",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("ShareOnlyMeeting")]
public JoinDataComplete ShareOnlyMeeting = new JoinDataComplete(
new JoinData
@@ -113,7 +120,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("StartNormalMeetingFromSharingOnlyMeeting")]
public JoinDataComplete StartNormalMeetingFromSharingOnlyMeeting = new JoinDataComplete(
new JoinData
@@ -367,6 +373,54 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital
});
[JoinName("MeetingCanRecord")]
public JoinDataComplete MeetingCanRecord = new JoinDataComplete(
new JoinData
{
JoinNumber = 246,
JoinSpan = 1
},
new JoinMetadata
{
Description = "When high, indicated that the current meeting can be recorded",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
#region Sharing Status
[JoinName("IsSharingAirplay")]
public JoinDataComplete IsSharingAirplay = new JoinDataComplete(
new JoinData
{
JoinNumber = 250,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Indicates an Airplay source is sharing",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IsSharingHdmi")]
public JoinDataComplete IsSharingHdmi = new JoinDataComplete(
new JoinData
{
JoinNumber = 251,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Indicates an HDMI source is sharing",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
#endregion
//[JoinName("ParticipantAudioMuteToggleStart")]
//public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete(
// new JoinData
@@ -551,6 +605,92 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.DigitalSerial
});
[JoinName("DisplayState")]
public JoinDataComplete DisplayState = new JoinDataComplete(
new JoinData
{
JoinNumber = 250,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the instructions the ZoomRoom is displaying on the monitor. <None | Laptop | IOS>",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("AirplayShareCode")]
public JoinDataComplete AirplayShareCode = new JoinDataComplete(
new JoinData
{
JoinNumber = 251,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the current code for Airplay Sharing.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("LaptopShareKey")]
public JoinDataComplete LaptopShareKey = new JoinDataComplete(
new JoinData
{
JoinNumber = 252,
JoinSpan = 1
},
new JoinMetadata
{
Description = "The alpha-only sharing key that users type into a laptop client to share with the Zoom Room.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("LaptopSharePairingCode")]
public JoinDataComplete LaptopSharePairingCode = new JoinDataComplete(
new JoinData
{
JoinNumber = 253,
JoinSpan = 1
},
new JoinMetadata
{
Description = "This is the paring code that is broadcast via an ultrasonic signal from the ZRC. It is different than the user-supplied paring code. The ZRC uses a Zoom-proprietary method of advertizing the ultrasonic pairing code, so it\'s not possible to advertize it using commonly available libraries.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("WifiName")]
public JoinDataComplete WifiName = new JoinDataComplete(
new JoinData
{
JoinNumber = 254,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the Wifi SSID used by the ZoomRoom.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ServerName")]
public JoinDataComplete ServerName = new JoinDataComplete(
new JoinData
{
JoinNumber = 255,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the namne of the the ZoomRoom.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
#endregion
public ZoomRoomJoinMap(uint joinStart)

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
@@ -29,11 +30,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/* This layout will be selected when Sharing starts (either from Far end or locally)*/
[JsonProperty("defaultSharingLayout")]
public string DefaultSharingLayout { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public zConfiguration.eLayoutStyle DefaultSharingLayout { get; set; }
//This layout will be selected when a call is connected and no content is being shared
[JsonProperty("defaultCallLayout")]
public string DefaultCallLayout { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public zConfiguration.eLayoutStyle DefaultCallLayout { get; set; }
[JsonProperty("minutesBeforeMeetingStart")]
public int MinutesBeforeMeetingStart { get; set; }