Merge branch 'release/1.10.0' into feature/add-cisco-room-kit-features

This commit is contained in:
Neil Dorin
2022-02-15 16:05:14 -07:00
72 changed files with 3631 additions and 980 deletions

View File

@@ -69,6 +69,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("directoryResults")]
public List<DirectoryItem> CurrentDirectoryResults { get; private set; }
[JsonProperty("contacts")]
public List<DirectoryItem> Contacts
{
get
@@ -77,6 +78,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
}
}
[JsonProperty("folders")]
public List<DirectoryItem> Folders
{
get

View File

@@ -124,6 +124,8 @@
<Compile Include="Cameras\CameraControl.cs" />
<Compile Include="Display\PanasonicThDisplay.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingInfo.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingLock.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingRecording.cs" />
<Compile Include="VideoCodec\Interfaces\IHasParticipants.cs" />
<Compile Include="VideoCodec\Interfaces\IHasPresentationOnlyMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" />

View File

@@ -19,7 +19,7 @@ namespace PepperDash.Essentials.Devices.Common
public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingOutputs
{
public IrOutputPortController IrPort { get; private set; }
public const string StandardDriverName = "Apple AppleTV-v2.ir";
public const string StandardDriverName = "Apple_AppleTV_4th_Gen_Essentials.ir";
public uint DisplayUiType { get { return DisplayUiConstants.TypeAppleTv; } }
public AppleTV(string key, string name, IrOutputPortController portCont)

View File

@@ -6,6 +6,8 @@ using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
/// <summary>
@@ -25,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary>
public interface IHasZoomRoomLayouts : IHasCodecLayouts
{
event EventHandler<LayoutInfoChangedEventArgs> AvailableLayoutsChanged;
event EventHandler<LayoutInfoChangedEventArgs> LayoutInfoChanged;
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
@@ -45,6 +47,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public class LayoutInfoChangedEventArgs : EventArgs
{
[JsonProperty("availableLayouts", NullValueHandling = NullValueHandling.Ignore)]
public ZoomRoom.zConfiguration.eLayoutStyle AvailableLayouts { get; set; }
[JsonProperty("currentSelectedLayout", NullValueHandling = NullValueHandling.Ignore)]
public ZoomRoom.zConfiguration.eLayoutStyle CurrentSelectedLayout { get; set; }
[JsonProperty("canSwapContentWithThumbnail", NullValueHandling = NullValueHandling.Ignore)]
public bool CanSwapContentWithThumbnail { get; set; }
[JsonProperty("contentSwappedWithThumbnail", NullValueHandling = NullValueHandling.Ignore)]
public bool ContentSwappedWithThumbnail { get; set; }
[JsonProperty("layoutViewIsOnFirstPage", NullValueHandling = NullValueHandling.Ignore)]
public bool LayoutViewIsOnFirstPage { get; set; }
[JsonProperty("layoutViewIsOnLastPage", NullValueHandling = NullValueHandling.Ignore)]
public bool LayoutViewIsOnLastPage { get; set; }
}
}

View File

@@ -24,24 +24,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary>
public class MeetingInfo
{
[JsonProperty("id")]
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public string Id { get; private set; }
[JsonProperty("name")]
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; private set; }
[JsonProperty("host")]
[JsonProperty("host", NullValueHandling = NullValueHandling.Ignore)]
public string Host { get; private set; }
[JsonProperty("password")]
[JsonProperty("password", NullValueHandling = NullValueHandling.Ignore)]
public string Password { get; private set; }
[JsonProperty("shareStatus")]
[JsonProperty("shareStatus", NullValueHandling = NullValueHandling.Ignore)]
public string ShareStatus { get; private set; }
[JsonProperty("isHost")]
[JsonProperty("isHost", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsHost { get; private set; }
[JsonProperty("isSharingMeeting")]
[JsonProperty("isSharingMeeting", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsSharingMeeting { get; private set; }
[JsonProperty("waitingForHost")]
[JsonProperty("waitingForHost", NullValueHandling = NullValueHandling.Ignore)]
public Boolean WaitingForHost { get; private set; }
[JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsLocked { get; private set; }
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost)
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked)
{
Id = id;
Name = name;
@@ -51,6 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
IsHost = isHost;
IsSharingMeeting = isSharingMeeting;
WaitingForHost = waitingForHost;
IsLocked = isLocked;
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
public interface IHasMeetingLock
{
BoolFeedback MeetingIsLockedFeedback { get; }
void LockMeeting();
void UnLockMeeting();
void ToggleMeetingLock();
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
public interface IHasMeetingRecording
{
BoolFeedback MeetingIsRecordingFeedback { get; }
void StartRecording();
void StopRecording();
void ToggleRecording();
}
}

View File

@@ -12,6 +12,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
public interface IHasParticipants
{
CodecParticipants Participants { get; }
/// <summary>
/// Removes the participant from the meeting
/// </summary>
/// <param name="participant"></param>
void RemoveParticipant(int userId);
/// <summary>
/// Sets the participant as the new host
/// </summary>
/// <param name="participant"></param>
void SetParticipantAsHost(int userId);
}
/// <summary>
@@ -29,6 +41,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary>
public interface IHasParticipantAudioMute : IHasParticipantVideoMute
{
/// <summary>
/// Mute audio of all participants
/// </summary>
void MuteAudioForAllParticipants();
void MuteAudioForParticipant(int userId);
void UnmuteAudioForParticipant(int userId);
void ToggleAudioForParticipant(int userId);

View File

@@ -4,6 +4,8 @@ using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
@@ -19,12 +21,19 @@ namespace PepperDash.Essentials.Devices.Common.Codec
/// </summary>
public abstract class VideoCodecInfo
{
[JsonProperty("multiSiteOptionIsEnabled", NullValueHandling = NullValueHandling.Ignore)]
public abstract bool MultiSiteOptionIsEnabled { get; }
[JsonProperty("ipAddress", NullValueHandling = NullValueHandling.Ignore)]
public abstract string IpAddress { get; }
[JsonProperty("sipPhoneNumber", NullValueHandling = NullValueHandling.Ignore)]
public abstract string SipPhoneNumber { get; }
[JsonProperty("e164Alias", NullValueHandling = NullValueHandling.Ignore)]
public abstract string E164Alias { get; }
[JsonProperty("h323Id", NullValueHandling = NullValueHandling.Ignore)]
public abstract string H323Id { get; }
[JsonProperty("sipUri", NullValueHandling = NullValueHandling.Ignore)]
public abstract string SipUri { get; }
[JsonProperty("autoAnswerEnabled", NullValueHandling = NullValueHandling.Ignore)]
public abstract bool AutoAnswerEnabled { get; }
}
}

View File

@@ -431,8 +431,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
m.MinutesBeforeMeeting = 5;
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.StartTime = DateTime.Now.AddMinutes(5).AddHours(i);
m.EndTime = DateTime.Now.AddHours(i).AddMinutes(50);
m.Title = "Meeting " + i;
m.Calls.Add(new Call() { Number = i + "meeting@fake.com"});
_CodecSchedule.Meetings.Add(m);
@@ -602,6 +602,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn);
SupportsCameraAutoMode = true;
CameraAutoModeIsOnFeedback.FireUpdate();
DeviceManager.AddDevice(internalCamera);
@@ -609,7 +611,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
NearEndPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco
NearEndPresets = PropertiesConfig.Presets;
if (PropertiesConfig.Presets != null && PropertiesConfig.Presets.Count > 0)
{
NearEndPresets = PropertiesConfig.Presets;
}
else
{
for (int i = 1; i <= NearEndPresets.Capacity; i++)
{
var label = string.Format("Near End Preset {0}", i);
NearEndPresets.Add(new CodecRoomPreset(i, label, true, false));
}
}
FarEndRoomPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco

View File

@@ -18,5 +18,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
[JsonProperty("presets")]
public List<CodecRoomPreset> Presets { get; set; }
public MockVcPropertiesConfig()
{
Favorites = new List<CodecActiveCallItem>();
Presets = new List<CodecRoomPreset>();
}
}
}

View File

@@ -41,6 +41,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
SharingSourceFeedback = new StringFeedback(SharingSourceFeedbackFunc);
SharingContentIsOnFeedback = new BoolFeedback(SharingContentIsOnFeedbackFunc);
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
MeetingsToDisplayFeedback = new IntFeedback(() => MeetingsToDisplay);
InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
@@ -305,8 +308,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC");
};
}
@@ -425,7 +426,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
if (codec is IHasCameraAutoMode)
{
trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true);
trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, SupportsCameraAutoMode);
(codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate();
}
@@ -598,6 +599,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
UpdateParticipantsXSig(codec, trilist, joinMap);
};
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.CurrentParticipants.JoinNumber, "\xFC");
UpdateParticipantsXSig(codec, trilist, joinMap);
};
}
private void UpdateParticipantsXSig(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
@@ -829,7 +839,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
UpdateMeetingsList(codec, trilist, joinMap);
}
};
}
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
trilist.SetUShortSigAction(joinMap.MeetingsToDisplay.JoinNumber, m => MeetingsToDisplay = m);
MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]);
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC");
UpdateMeetingsList(codec, trilist, joinMap);
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]);
};
}
private void UpdateMeetingsList(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
@@ -850,19 +875,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
var meetingsData = UpdateMeetingsListXSig(_currentMeetings);
trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData);
trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count);
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC");
UpdateMeetingsListXSig(_currentMeetings);
};
}
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
private int _meetingsToDisplay = 3;
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
protected int MeetingsToDisplay
{
get { return _meetingsToDisplay; }
set {
_meetingsToDisplay = (ushort) (value == 0 ? 3 : value);
MeetingsToDisplayFeedback.FireUpdate();
}
}
// TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set
public IntFeedback MeetingsToDisplayFeedback { get; set; }
private string UpdateMeetingsListXSig(List<Meeting> meetings)
{
const int maxMeetings = 3;
// 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 * maxMeetings; //15
var digitalIndex = maxStrings * _meetingsToDisplay; //15
var stringIndex = 0;
var meetingIndex = 0;
var tokenArray = new XSigToken[maxMeetings * offset];
var tokenArray = new XSigToken[_meetingsToDisplay * offset];
/*
* Digitals
* IsJoinable - 1
@@ -885,7 +936,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
if (meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue;
if (meetingIndex >= maxMeetings * offset)
if (meetingIndex >= _meetingsToDisplay * offset)
{
Debug.Console(2, this, "Max Meetings reached");
break;
@@ -910,10 +961,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
stringIndex += maxStrings;
}
while (meetingIndex < maxMeetings * offset)
while (meetingIndex < _meetingsToDisplay * offset)
{
Debug.Console(2, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}",
meetingIndex, maxMeetings * offset);
meetingIndex, _meetingsToDisplay * offset);
//digitals
tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false);
@@ -980,6 +1031,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
};
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, "\xFC");
UpdateDirectoryXSig(codec.CurrentDirectoryResult,
!codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
};
}
@@ -1207,80 +1268,88 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig());
trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count);
trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count);
};
var joinCodec = this as IJoinCalls;
if (joinCodec != null)
{
trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls());
var joinCodec = this as IJoinCalls;
if (joinCodec != null)
{
trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls());
for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++)
{
trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () =>
{
var call = ActiveCalls[i];
if (call != null)
{
joinCodec.JoinCall(call);
}
else
{
Debug.Console(0, this, "[Join Call] Unable to find call at index '{0}'", i);
}
});
}
}
for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++)
{
trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () =>
{
var call = ActiveCalls[i];
if (call != null)
{
joinCodec.JoinCall(call);
}
else
{
Debug.Console(0, this, "[Join Call] Unable to find call at index '{0}'", i);
}
});
}
}
var holdCodec = this as IHasCallHold;
if (holdCodec != null)
{
trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () =>
{
foreach (var call in ActiveCalls)
{
holdCodec.HoldCall(call);
}
});
var holdCodec = this as IHasCallHold;
if (holdCodec != null)
{
trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () =>
{
foreach (var call in ActiveCalls)
{
holdCodec.HoldCall(call);
}
});
for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++)
{
var index = i;
for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++)
{
var index = i;
trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.HoldCall(call);
}
else
{
Debug.Console(0, this, "[Hold Call] Unable to find call at index '{0}'", i);
}
});
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.HoldCall(call);
}
else
{
Debug.Console(0, this, "[Hold Call] Unable to find call at index '{0}'", i);
}
});
trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.ResumeCall(call);
}
else
{
Debug.Console(0, this, "[Resume Call] Unable to find call at index '{0}'", i);
}
});
}
}
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.ResumeCall(call);
}
else
{
Debug.Console(0, this, "[Resume Call] Unable to find call at index '{0}'", i);
}
});
}
}
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC");
UpdateCallStatusXSig();
};
}
private string UpdateCallStatusXSig()
@@ -1664,6 +1733,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.UShortOutput[joinMap.CameraPresetSelect.JoinNumber].UShortValue, String.Empty);
trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000);
});
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.CameraPresetNames.JoinNumber, "\xFC");
SetCameraPresetNames(presetCodec.NearEndPresets);
};
}
// Following fields only used for Bridging

View File

@@ -618,13 +618,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private bool _can_Switch_Speaker_View;
private bool _can_Switch_Wall_View;
private bool _can_Switch_Share_On_All_Screens;
private bool _can_Switch_Floating_Share_Content;
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_Switch_Floating_Share_Content { get; set; }
public bool can_Switch_Floating_Share_Content
{
get
{
return _can_Switch_Floating_Share_Content;
}
set
{
if (value != _can_Switch_Floating_Share_Content)
{
_can_Switch_Floating_Share_Content = value;
NotifyPropertyChanged("can_Switch_Floating_Share_Content");
}
}
}
/// <summary>
/// [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.
@@ -744,12 +762,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
public class CallRecordInfo
public class CallRecordInfo : NotifiableObject
{
private bool _meetingIsBeingRecorded;
public bool canRecord { get; set; }
public bool emailRequired { get; set; }
public bool amIRecording { get; set; }
public bool meetingIsBeingRecorded { get; set; }
public bool meetingIsBeingRecorded
{
get
{
return _meetingIsBeingRecorded;
}
set
{
if (value != _meetingIsBeingRecorded)
{
_meetingIsBeingRecorded = value;
NotifyPropertyChanged("meetingIsBeingRecorded");
}
}
}
}
}
@@ -1123,9 +1158,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
public class Lock
public class Lock : NotifiableObject
{
public bool Enable { get; set; }
private bool _enable;
public bool Enable
{
get
{
return _enable;
}
set
{
if (value != _enable)
{
_enable = value;
NotifyPropertyChanged("Enable");
}
}
}
}
public class ClosedCaption

View File

@@ -26,13 +26,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
IRouting,
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting,
IHasMeetingLock, IHasMeetingRecording
{
private const long MeetingRefreshTimer = 60000;
public uint DefaultMeetingDurationMin { get; private set; }
private const string Delimiter = "\x0D\x0A";
/// <summary>
/// CR LF
/// </summary>
private const string EchoDelimiter = "\x0D\x0A\x0D\x0A";
private const string SendDelimiter = "\x0D";
/// <summary>
/// CR LF } CR LF
/// </summary>
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;
@@ -58,7 +71,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_props = JsonConvert.DeserializeObject<ZoomRoomPropertiesConfig>(config.Properties.ToString());
_receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512);
_receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 2048);
Communication = comm;
@@ -70,7 +83,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
else
{
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000,
"zStatus SystemUnit\r");
"zStatus SystemUnit" + SendDelimiter);
}
DeviceManager.AddDevice(CommunicationMonitor);
@@ -85,9 +98,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted;
_syncState.FirstJsonResponseReceived += (o, a) => SetUpSyncQueries();
PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync");
PortGather = new CommunicationGather(Communication, "\x0A") {IncludeDelimiter = true};
PhonebookSyncState.InitialSyncCompleted += (o, a) => ResubscribeForAddedContacts();
PortGather = new CommunicationGather(Communication, Delimiters) {IncludeDelimiter = true};
PortGather.LineReceived += Port_LineReceived;
CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd,
@@ -147,6 +164,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc);
NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc);
MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable );
MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded );
}
public CommunicationGather PortGather { get; private set; }
@@ -499,19 +520,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
var sharingStatus = GetSharingStatus();
MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false);
MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue);
return;
}
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None",
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost);
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue);
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);
MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue);
}
}
@@ -578,11 +599,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
case "ShareThumb":
{
ContentSwappedWithThumbnailFeedback.FireUpdate();
OnLayoutInfoChanged();
break;
}
case "Style":
{
LocalLayoutFeedback.FireUpdate();
OnLayoutInfoChanged();
break;
}
case "Size":
@@ -597,6 +620,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
};
Configuration.Call.Lock.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "Enable")
{
MeetingIsLockedFeedback.FireUpdate();
MeetingInfo = new MeetingInfo
(
MeetingInfo.Id,
MeetingInfo.Name,
MeetingInfo.Host,
MeetingInfo.Password,
GetSharingStatus(),
MeetingInfo.IsHost,
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue
);
}
};
// This is to deal with incorrect object structure coming back from the Zoom Room on v 5.6.3
Configuration.Client.Call.Layout.PropertyChanged += (o, a) =>
{
@@ -613,11 +656,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
case "ShareThumb":
{
ContentSwappedWithThumbnailFeedback.FireUpdate();
OnLayoutInfoChanged();
break;
}
case "Style":
{
LocalLayoutFeedback.FireUpdate();
OnLayoutInfoChanged();
break;
}
}
@@ -634,13 +679,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Status.Call.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "Info")
switch(a.PropertyName)
{
case "Info":
{
Debug.Console(1, this, "Updating Call Status");
UpdateCallStatus();
break;
}
case "Status":
{
UpdateCallStatus();
break;
}
}
};
Status.Call.CallRecordInfo.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "meetingIsBeingRecorded")
{
MeetingIsRecordingFeedback.FireUpdate();
}
};
Status.Sharing.PropertyChanged += (o, a) =>
{
switch (a.PropertyName)
@@ -663,7 +726,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
return;
}
// Update the share status of the meeting info
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost);
var meetingInfo = new MeetingInfo(MeetingInfo.Id,
MeetingInfo.Name,
MeetingInfo.Host,
MeetingInfo.Password,
GetSharingStatus(),
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue);
MeetingInfo = meetingInfo;
break;
}
@@ -714,13 +785,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
LayoutViewIsOnLastPageFeedback.FireUpdate();
break;
}
//case "video_type":
// {
// It appears as though the actual value we want to watch is Configuration.Call.Layout.Style
// LocalLayoutFeedback.FireUpdate();
// break;
// }
case "can_Switch_Floating_Share_Content":
{
CanSwapContentWithThumbnailFeedback.FireUpdate();
break;
}
}
OnLayoutInfoChanged();
};
Status.NumberOfScreens.PropertyChanged += (o, a) =>
@@ -849,7 +920,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Debug.Console(1, this, "Sending: '{0}'", command);
}
Communication.SendText(command + Delimiter);
Communication.SendText(command + SendDelimiter);
}
/// <summary>
@@ -859,13 +930,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <param name="args"></param>
private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
{
//if (CommDebuggingIsOn)
// Debug.Console(1, this, "Gathered: '{0}'", args.Text);
//Debug.Console(0, this, "Port_LineReceived");
_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage));
if (args.Delimiter != JsonDelimiter)
{
// Debug.Console(0, this,
//@"Non JSON response:
//Delimiter: {0}
//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text);
ProcessNonJsonResponse(args.Text);
return;
}
else
{
// Debug.Console(0, this,
//@"JSON response:
//Delimiter: {0}
//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text);
_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, DeserializeResponse));
//_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage));
}
}
/// <summary>
/// Queues the initial queries to be sent upon connection
/// </summary>
@@ -924,6 +1010,93 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncState.StartSync();
}
private void SetupSession()
{
// disable echo of commands
SendText("echo off");
// switch to json format
// set feedback exclusions
// Currently the feedback exclusions don't work when using the API in JSON response mode
// But leave these here in case the API gets updated in the future
// These may work as of 5.9.4
// In 5.9.4 we're getting sent an AddedContact message for every contact in the phonebook on connect, which is redunant and way too much data
// We want to exclude these messages right away until after we've retrieved the entire phonebook and then we can re-enable them
SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
SendText("zStatus SystemUnit");
}
/// <summary>
/// Removes the feedback exclusion for added contacts
/// </summary>
private void ResubscribeForAddedContacts()
{
SendText("zFeedback Register Op: in Path: /Event/Phonebook/AddedContact");
}
/// <summary>
/// Processes non-JSON responses as their are received
/// </summary>
/// <param name="response"></param>
private void ProcessNonJsonResponse(string response)
{
if (response.Contains("client_loop: send disconnect: Broken pipe"))
{
Debug.Console(1, this, Debug.ErrorLogLevel.Error,
"Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected.");
return;
}
if (!_syncState.InitialSyncComplete)
{
if(response.ToLower().Contains("*r login successful"))
{
_syncState.LoginResponseReceived();
SendText("format json");
SetupSession();
}
//switch (response.Trim().ToLower()) // remove the whitespace
//{
// case "*r login successful":
// {
// _syncState.LoginMessageReceived();
// //// Fire up a thread to send the intial commands.
// //CrestronInvoke.BeginInvoke(o =>
// //{
// // disable echo of commands
// SendText("echo off");
// // switch to json format
// SendText("format json");
// // set feedback exclusions
// // Currently the feedback exclusions don't work when using the API in JSON response mode
// // But leave these here in case the API gets updated in the future
// // These may work as of 5.9.4
// if (_props.DisablePhonebookAutoDownload)
// {
// SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
// }
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list");
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list");
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
// //});
// break;
// }
//}
}
}
/// <summary>
/// Processes messages as they are dequeued
/// </summary>
@@ -951,7 +1124,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
//Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter);
if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter)
if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + EchoDelimiter)
// Check for the beginning of a new JSON message
{
_jsonFeedbackMessageIsIncoming = true;
@@ -968,7 +1141,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
return;
}
if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter)
if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + EchoDelimiter)
// Check for the end of a JSON message
{
_jsonMessage.Append(message);
@@ -1013,7 +1186,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
case "*r login successful":
{
_syncState.LoginMessageReceived();
_syncState.LoginResponseReceived();
// Fire up a thread to send the intial commands.
@@ -1035,7 +1208,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
Thread.Sleep(100);
if (!_props.DisablePhonebookAutoDownload)
if (_props.DisablePhonebookAutoDownload)
{
SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
}
@@ -1066,6 +1239,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var message = JObject.Parse(trimmedResponse);
if (!_syncState.FirstJsonResponseWasReceived)
{
_syncState.ReceivedFirstJsonResponse();
}
var eType =
(eZoomRoomResponseType)
Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value<string>(), true);
@@ -1074,7 +1252,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var responseObj = message[topKey];
Debug.Console(1, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString());
Debug.Console(1, this, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString().Replace("\n", CrestronEnvironment.NewLine));
switch (eType)
{
@@ -1244,7 +1422,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Participants.CurrentParticipants = participants;
// Update the share status of the meeting info
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host.Name, MeetingInfo.Password, MeetingInfo.ShareStatus, GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost);
var meetingInfo = new MeetingInfo(
MeetingInfo.Id,
MeetingInfo.Name,
Participants.Host.Name,
MeetingInfo.Password,
MeetingInfo.ShareStatus,
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue);
MeetingInfo = meetingInfo;
PrintCurrentCallParticipants();
@@ -1446,21 +1633,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
Status.NeedWaitForHost = JsonConvert.DeserializeObject<zEvent.NeedWaitForHost>(responseObj.ToString());
Debug.Console(1, this, "NeedWaitForHost: {0}", Status.NeedWaitForHost.Wait);
Debug.Console(1, this, "WaitingForHost: {0}", Status.NeedWaitForHost.Wait);
if (Status.NeedWaitForHost.Wait)
{
if (MeetingInfo == null)
{
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true);
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue);
UpdateCallStatus();
break;
}
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true);
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue);
UpdateCallStatus();
@@ -1470,12 +1657,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);
GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue);
break;
}
MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password,
GetSharingStatus(), GetIsHostMyself(), false, false);
GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue);
break;
}
@@ -1559,7 +1746,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (result.Success)
{
MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost);
MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue);
break;
}
@@ -1578,19 +1765,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
case "login":
{
_syncState.LoginMessageReceived();
_syncState.LoginResponseReceived();
if (!_syncState.InitialQueryMessagesWereSent)
{
SetUpSyncQueries();
}
SetupSession();
JsonConvert.PopulateObject(responseObj.ToString(), Status.Login);
break;
}
case "systemunit":
{
{
JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit);
break;
@@ -1904,6 +2089,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetSharingStatus(),
GetIsHostMyself(),
!String.Equals(Status.Call.Info.meeting_type,"NORMAL"),
false,
MeetingIsLockedFeedback.BoolValue
);
}
// TODO [ ] Issue #868
else if (item.Status == eCodecCallStatus.Disconnected)
{
MeetingInfo = new MeetingInfo(
string.Empty,
string.Empty,
string.Empty,
string.Empty,
string.Empty,
false,
false,
false,
false
);
}
@@ -2132,16 +2333,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var layoutsCodec = this as IHasZoomRoomLayouts;
if (layoutsCodec != null)
{
layoutsCodec.AvailableLayoutsChanged += (o, a) =>
layoutsCodec.LayoutInfoChanged += (o, a) =>
{
trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Gallery
==
(a.AvailableLayouts &
zConfiguration.eLayoutStyle.Gallery));
trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Speaker
==
(a.AvailableLayouts &
zConfiguration.eLayoutStyle.Speaker));
trilist.SetBool(joinMap.LayoutGalleryIsAvailable.JoinNumber,
zConfiguration.eLayoutStyle.Gallery == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Gallery));
trilist.SetBool(joinMap.LayoutSpeakerIsAvailable.JoinNumber,
zConfiguration.eLayoutStyle.Speaker == (a.AvailableLayouts & zConfiguration.eLayoutStyle.Speaker));
trilist.SetBool(joinMap.LayoutStripIsAvailable.JoinNumber, zConfiguration.eLayoutStyle.Strip
==
(a.AvailableLayouts & zConfiguration.eLayoutStyle.Strip));
@@ -2196,7 +2397,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
trilist.SetUShortSigAction(joinMap.ScreenIndexToPinUserTo.JoinNumber, (u) => ScreenIndexToPinUserTo = u);
}
// TODO: #714 [ ] LinkZoomRoomToApi >> layoutSizeCoodec
var layoutSizeCodec = this as IHasSelfviewSize;
if (layoutSizeCodec != null)
{
@@ -2218,6 +2418,75 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
layoutSizeCodec.SelfviewPipSizeFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetSelfviewPipSize.JoinNumber]);
}
PasswordRequired += (device, args) =>
{
if (args.LoginAttemptCancelled)
{
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false);
return;
}
if (!string.IsNullOrEmpty(args.Message))
{
trilist.SetString(joinMap.PasswordPromptMessage.JoinNumber, args.Message);
}
if (args.LoginAttemptFailed)
{
trilist.SetBool(joinMap.PasswordLoginFailed.JoinNumber, true);
return;
}
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, true);
};
MeetingInfoChanged += (device, args) =>
{
trilist.SetString(joinMap.MeetingInfoId.JoinNumber, args.Info.Id);
trilist.SetString(joinMap.MeetingInfoHost.JoinNumber, args.Info.Host);
trilist.SetString(joinMap.MeetingInfoPassword.JoinNumber, args.Info.Password);
trilist.SetBool(joinMap.IsHost.JoinNumber, args.Info.IsHost);
trilist.SetBool(joinMap.ShareOnlyMeeting.JoinNumber, args.Info.IsSharingMeeting);
trilist.SetBool(joinMap.WaitingForHost.JoinNumber, args.Info.WaitingForHost);
//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.SetStringSigAction(joinMap.SubmitPassword.JoinNumber, SubmitPassword);
PasswordRequired += (devices, args) =>
{
if (args.LoginAttemptCancelled)
{
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false);
return;
}
if (!string.IsNullOrEmpty(args.Message))
{
trilist.SetString(joinMap.PasswordPromptMessage.JoinNumber, args.Message);
}
if (args.LoginAttemptFailed)
{
// login attempt failed
return;
}
trilist.SetBool(joinMap.PasswordIncorrect.JoinNumber, args.LastAttemptWasIncorrect);
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, true);
};
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
@@ -2334,6 +2603,56 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
/// <summary>
/// Invites contacts to a new meeting for a specified duration
/// </summary>
/// <param name="contacts"></param>
/// <param name="duration"></param>
public void InviteContactsToNewMeeting(List<InvitableDirectoryContact> contacts, uint duration)
{
if(duration == 0)
{
duration = DefaultMeetingDurationMin;
}
StringBuilder message = new StringBuilder();
// Add the prefix
message.Append(string.Format("zCommand Invite Duration: {0}", duration));
// Add each invitee
foreach (var contact in contacts)
{
var invitee = string.Format(" user: {0}", contact.ContactId);
message.Append(invitee);
}
SendText(message.ToString());
}
/// <summary>
/// Invites contacts to an existing meeting
/// </summary>
/// <param name="contacts"></param>
public void InviteContactsToExistingMeeting(List<InvitableDirectoryContact> contacts)
{
StringBuilder message = new StringBuilder();
// Add the prefix
message.Append(string.Format("zCommand Call Invite"));
// Add each invitee
foreach (var contact in contacts)
{
var invitee = string.Format(" user: {0}", contact.ContactId);
message.Append(invitee);
}
SendText(message.ToString());
}
/// <summary>
/// Starts a PMI Meeting for the specified duration (or default meeting duration if 0 is specified)
@@ -2469,10 +2788,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public CodecParticipants Participants { get; private set; }
public void RemoveParticipant(int userId)
{
SendText(string.Format("zCommand Call Expel Id: {0}", userId));
}
public void SetParticipantAsHost(int userId)
{
SendText(string.Format("zCommand Call HostChange Id: {0}", userId));
}
#endregion
#region IHasParticipantAudioMute Members
public void MuteAudioForAllParticipants()
{
SendText(string.Format("zCommand Call MuteAll Mute: on"));
}
public void MuteAudioForParticipant(int userId)
{
SendText(string.Format("zCommand Call MuteParticipant Mute: on Id: {0}", userId));
@@ -2770,7 +3104,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
#region IHasZoomRoomLayouts Members
public event EventHandler<LayoutInfoChangedEventArgs> AvailableLayoutsChanged;
public event EventHandler<LayoutInfoChangedEventArgs> LayoutInfoChanged;
private Func<bool> LayoutViewIsOnFirstPageFeedbackFunc
{
@@ -2836,15 +3170,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Debug.Console(1, this, "availablelayouts: {0}", availableLayouts);
var handler = AvailableLayoutsChanged;
if (handler != null)
{
handler(this, new LayoutInfoChangedEventArgs() {AvailableLayouts = availableLayouts});
}
AvailableLayouts = availableLayouts;
}
private void OnLayoutInfoChanged()
{
var handler = LayoutInfoChanged;
if (handler != null)
{
handler(this, new LayoutInfoChangedEventArgs()
{
AvailableLayouts = AvailableLayouts,
CurrentSelectedLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle),string.IsNullOrEmpty(LocalLayoutFeedback.StringValue) ? "None" : LocalLayoutFeedback.StringValue , true),
LayoutViewIsOnFirstPage = LayoutViewIsOnFirstPageFeedback.BoolValue,
LayoutViewIsOnLastPage = LayoutViewIsOnLastPageFeedback.BoolValue,
CanSwapContentWithThumbnail = CanSwapContentWithThumbnailFeedback.BoolValue,
ContentSwappedWithThumbnail = ContentSwappedWithThumbnailFeedback.BoolValue,
});
}
}
public void GetAvailableLayouts()
{
SendText("zStatus Call Layout");
@@ -3034,7 +3379,63 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
#endregion
}
#region IHasMeetingLock Members
public BoolFeedback MeetingIsLockedFeedback { get; private set; }
public void LockMeeting()
{
SendText(string.Format("zConfiguration Call Lock Enable: on"));
}
public void UnLockMeeting()
{
SendText(string.Format("zConfiguration Call Lock Enable: off"));
}
public void ToggleMeetingLock()
{
if (MeetingIsLockedFeedback.BoolValue)
{
UnLockMeeting();
}
else
{
LockMeeting();
}
}
#endregion
#region IHasMeetingRecording Members
public BoolFeedback MeetingIsRecordingFeedback { get; private set; }
public void StartRecording()
{
SendText(string.Format("Command Call Record Enable: on"));
}
public void StopRecording()
{
SendText(string.Format("Command Call Record Enable: off"));
}
public void ToggleRecording()
{
if (MeetingIsRecordingFeedback.BoolValue)
{
StopRecording();
}
else
{
StartRecording();
}
}
#endregion
}
/// <summary>
/// Zoom Room specific info object
@@ -3047,8 +3448,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Configuration = configuration;
}
[JsonIgnore]
public ZoomRoomStatus Status { get; private set; }
public ZoomRoomConfiguration Configuration { get; private set; }
[JsonIgnore]
public ZoomRoomConfiguration Configuration { get; private set; }
public override bool AutoAnswerEnabled
{
@@ -3155,7 +3558,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
public bool LoginMessageWasReceived { get; private set; }
public bool LoginResponseWasReceived { get; private set; }
public bool FirstJsonResponseWasReceived { get; private set; }
public bool InitialQueryMessagesWereSent { get; private set; }
@@ -3171,6 +3576,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public event EventHandler<EventArgs> InitialSyncCompleted;
public event EventHandler FirstJsonResponseReceived;
public void StartSync()
{
DequeueQueries();
@@ -3193,14 +3600,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncQueries.Enqueue(query);
}
public void LoginMessageReceived()
public void LoginResponseReceived()
{
LoginMessageWasReceived = true;
Debug.Console(1, this, "Login Message Received.");
LoginResponseWasReceived = true;
Debug.Console(1, this, "Login Rsponse Received.");
CheckSyncStatus();
}
private void InitialQueryMessagesSent()
public void ReceivedFirstJsonResponse()
{
FirstJsonResponseWasReceived = true;
Debug.Console(1, this, "First JSON Response Received.");
var handler = FirstJsonResponseReceived;
if (handler != null)
{
handler(this, null);
}
CheckSyncStatus();
}
public void InitialQueryMessagesSent()
{
InitialQueryMessagesWereSent = true;
Debug.Console(1, this, "Query Messages Sent.");
@@ -3224,7 +3644,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public void CodecDisconnected()
{
_syncQueries.Clear();
LoginMessageWasReceived = false;
LoginResponseWasReceived = false;
FirstJsonResponseWasReceived = false;
InitialQueryMessagesWereSent = false;
LastQueryResponseWasReceived = false;
CamerasHaveBeenSetUp = false;
@@ -3233,7 +3654,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void CheckSyncStatus()
{
if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived &&
if (LoginResponseWasReceived && FirstJsonResponseWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived &&
CamerasHaveBeenSetUp)
{
InitialSyncComplete = true;

View File

@@ -1,301 +1,496 @@
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)
{
}
}
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
// TODO [ ] Issue #868
[JoinName("ShowPasswordPrompt")]
public JoinDataComplete ShowPasswordPrompt = new JoinDataComplete(
new JoinData
{
JoinNumber = 6,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates to show the password prompt",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("PasswordIncorrect")]
public JoinDataComplete PasswordIncorrect = new JoinDataComplete(
new JoinData
{
JoinNumber = 7,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates the password entered is incorrect",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("PassowrdLoginFailed")]
public JoinDataComplete PasswordLoginFailed = new JoinDataComplete(
new JoinData
{
JoinNumber = 8,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates the password entered is incorrect",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("WaitingForHost")]
public JoinDataComplete WaitingForHost = new JoinDataComplete(
new JoinData
{
JoinNumber = 9,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates system is waiting for host",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("IsHost")]
public JoinDataComplete IsHost = new JoinDataComplete(
new JoinData
{
JoinNumber = 10,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates system is the host",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("StartMeetingNow")]
public JoinDataComplete StartMeetingNow = new JoinDataComplete(
new JoinData
{
JoinNumber = 25,
JoinSpan = 1
},
new JoinMetadata
{
Description = "FB Indicates the password prompt is active",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("ShareOnlyMeeting")]
public JoinDataComplete ShareOnlyMeeting = new JoinDataComplete(
new JoinData
{
JoinNumber = 26,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Triggers a share only meeting, feedback indicates the current meeting is share only",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
// TODO [ ] Issue #868
[JoinName("StartNormalMeetingFromSharingOnlyMeeting")]
public JoinDataComplete StartNormalMeetingFromSharingOnlyMeeting = new JoinDataComplete(
new JoinData
{
JoinNumber = 27,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Starts a normal meeting from a share only meeting",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.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
// TODO [ ] Issue #868
[JoinName("SubmitPassword")]
public JoinDataComplete SubmitPassword = new JoinDataComplete(
new JoinData
{
JoinNumber = 6,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Submit password text",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
// TODO [ ] Issue #868
[JoinName("PasswordPromptMessage")]
public JoinDataComplete PasswordPromptMessage = new JoinDataComplete(
new JoinData
{
JoinNumber = 6,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Password prompt message",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
// TODO [ ] Issue #868
[JoinName("MeetingInfoId")]
public JoinDataComplete MeetingInfoId = new JoinDataComplete(
new JoinData
{
JoinNumber = 11,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Meeting info ID text feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
// TODO [ ] Issue #868
[JoinName("MeetingInfoHostt")]
public JoinDataComplete MeetingInfoHost = new JoinDataComplete(
new JoinData
{
JoinNumber = 12,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Meeting info Host text feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
// TODO [ ] Issue #868
[JoinName("MeetingInfoPassword")]
public JoinDataComplete MeetingInfoPassword = new JoinDataComplete(
new JoinData
{
JoinNumber = 13,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Meeting info Password text feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[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

@@ -2,30 +2,40 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{
public class ZoomRoomPropertiesConfig
{
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
public bool DisablePhonebookAutoDownload { get; set; }
public bool SupportsCameraAutoMode { get; set; }
{
[JsonProperty("communicationMonitorProperties")]
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
[JsonProperty("disablePhonebookAutoDownload")]
public bool DisablePhonebookAutoDownload { get; set; }
[JsonProperty("supportsCameraAutoMode")]
public bool SupportsCameraAutoMode { get; set; }
[JsonProperty("supportsCameraOff")]
public bool SupportsCameraOff { get; set; }
//if true, the layouts will be set automatically when sharing starts/ends or a call is joined
//if true, the layouts will be set automatically when sharing starts/ends or a call is joined
[JsonProperty("autoDefaultLayouts")]
public bool AutoDefaultLayouts { get; set; }
/* This layout will be selected when Sharing starts (either from Far end or locally)*/
/* This layout will be selected when Sharing starts (either from Far end or locally)*/
[JsonProperty("defaultSharingLayout")]
public string DefaultSharingLayout { get; set; }
//This layout will be selected when a call is connected and no content is being shared
public string DefaultCallLayout { 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; }
[JsonProperty("minutesBeforeMeetingStart")]
public int MinutesBeforeMeetingStart { get; set; }
}
}