diff --git a/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs b/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs index de26d3dc..51e8724b 100644 --- a/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs +++ b/Essentials Devices Common/Essentials Devices Common/Codec/iHasCallHistory.cs @@ -5,6 +5,7 @@ using System.Text; using Crestron.SimplSharp; using PepperDash.Core; +using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Devices.Common.Codec @@ -54,16 +55,16 @@ namespace PepperDash.Essentials.Devices.Common.Codec { handler(this, new EventArgs()); - if (Debug.Level == 1) - { + //if (Debug.Level == 1) + //{ - Debug.Console(1, "RecentCalls:\n"); + // Debug.Console(1, "RecentCalls:\n"); - foreach (CodecCallHistory.CallHistoryEntry entry in RecentCalls) - { - Debug.Console(1, "\nName: {0}\nNumber: {1}\nStartTime: {2}\nType: {3}\n", entry.Name, entry.Number, entry.StartTime.ToString(), entry.OccurenceType); - } - } + // foreach (CodecCallHistory.CallHistoryEntry entry in RecentCalls) + // { + // Debug.Console(1, "\nName: {0}\nNumber: {1}\nStartTime: {2}\nType: {3}\n", entry.Name, entry.Number, entry.StartTime.ToString(), entry.OccurenceType); + // } + //} } } @@ -94,13 +95,14 @@ namespace PepperDash.Essentials.Devices.Common.Codec foreach (CiscoCallHistory.Entry entry in entries) { + genericEntries.Add(new CallHistoryEntry() { Name = entry.DisplayName.Value, Number = entry.CallbackNumber.Value, StartTime = entry.LastOccurrenceStartTime.Value, OccurrenceHistoryId = entry.LastOccurrenceHistoryId.Value, - OccurenceType = ConvertToOccurenceTypeEnum(entry.OccurrenceType.Value) + OccurenceType = ConvertToOccurenceTypeEnum(entry.OccurrenceType.Value) }); } diff --git a/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs b/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs index ba1c709b..07225be0 100644 --- a/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs +++ b/Essentials Devices Common/Essentials Devices Common/Codec/iHasDirectory.cs @@ -15,6 +15,8 @@ namespace PepperDash.Essentials.Devices.Common.Codec CodecDirectory DirectoryRoot { get; } + CodecPhonebookSyncState PhonebookSyncState { get; } + void SearchDirectory(string searchString); void GetDirectoryFolderContents(string folderId); @@ -29,7 +31,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec { public List DirectoryResults { get; private set; } - //public int Offset { get; private set; } + public string ResultsFolderId { get; set; } //public int Limit { get; private set; } diff --git a/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs b/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs index 0ca05ee0..cfd00de9 100644 --- a/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs +++ b/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs @@ -132,8 +132,24 @@ namespace PepperDash.Essentials.Devices.Common.Codec && DateTime.Now <= EndTime.AddMinutes(-5); } } - public string ConferenceNumberToDial { get; set; } + //public string ConferenceNumberToDial { get; set; } public string ConferencePassword { get; set; } + public bool IsOneButtonToPushMeeting { get; set; } + + public List Calls { get; private set; } + + public Meeting() + { + Calls = new List(); + } + } + + public class Call + { + public string Number { get; set; } + public string Protocol { get; set; } + public string CallRate { get; set; } + public string CallType { get; set; } } public class MeetingEventArgs : EventArgs diff --git a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index 76037968..39fd0c66 100644 --- a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -136,8 +136,8 @@ - - + + diff --git a/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs b/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs index 94638472..0ef5bf24 100644 --- a/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs +++ b/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs @@ -109,11 +109,11 @@ namespace PepperDash.Essentials.Devices.Common .MockVC(key, name, props); } - else if (typeName == "ciscocodec") + else if (typeName.StartsWith("ciscospark")) { var comm = CommFactory.CreateCommForDevice(dc); - var props = JsonConvert.DeserializeObject(properties.ToString()); - return new PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoCodec(key, name, comm, props); + var props = JsonConvert.DeserializeObject(properties.ToString()); + return new PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoSparkCodec(key, name, comm, props); } else if (groupName == "settopbox") //(typeName == "irstbbase") diff --git a/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs b/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs index d89993f2..999e1a21 100644 --- a/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs +++ b/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs @@ -189,8 +189,32 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public string Value { get; set; } } - public class Calls + public class Number { + public string Value { get; set; } + } + + public class Protocol + { + public string Value { get; set; } + } + + public class CallRate + { + public string Value { get; set; } + } + + public class CallType + { + public string Value { get; set; } + } + + public class Call + { + public Number Number { get; set; } + public Protocol Protocol { get; set; } + public CallRate CallRate { get; set; } + public CallType CallType { get; set; } } public class ConnectMode @@ -200,8 +224,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public class DialInfo { - public Calls Calls { get; set; } + public List Calls { get; set; } public ConnectMode ConnectMode { get; set; } + + public DialInfo() + { + Calls = new List(); + } } public class Booking @@ -231,6 +260,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec Title = new Title(); Agenda = new Agenda(); Privacy = new Privacy(); + DialInfo = new DialInfo(); } } @@ -270,13 +300,36 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { var meeting = new Meeting(); - meeting.Id = b.Id.Value; - meeting.Organizer = string.Format("{0}, {1}", b.Organizer.LastName.Value, b.Organizer.FirstName.Value); - meeting.Title = b.Title.Value; - meeting.Agenda = b.Agenda.Value; - meeting.StartTime = b.Time.StartTime.Value; - meeting.EndTime = b.Time.EndTime.Value; - meeting.Privacy = CodecCallPrivacy.ConvertToDirectionEnum(b.Privacy.Value); + 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; + + foreach (Call c in b.DialInfo.Calls) + { + 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); @@ -284,7 +337,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { 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}", meeting.Joinable); + Debug.Console(1, " Joinable: {0}\n", meeting.Joinable); } } diff --git a/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodec.cs b/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs similarity index 90% rename from Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodec.cs rename to Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 0ee4034b..d43ca5f7 100644 --- a/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodec.cs +++ b/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { enum eCommandType { SessionStart, SessionEnd, Command, GetStatus, GetConfiguration }; - public class CiscoCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory, + public class CiscoSparkCodec : VideoCodecBase, IHasCallHistory, IHasCallFavorites, IHasDirectory, IHasScheduleAwareness, IOccupancyStatusProvider, IHasCodecLayouts, IHasCodecSelfview { public event EventHandler DirectoryResultReturned; @@ -188,7 +188,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco private CodecSyncState SyncState; - private CodecPhonebookSyncState PhonebookSyncState; + public CodecPhonebookSyncState PhonebookSyncState { get; private set; } private StringBuilder JsonMessage; @@ -214,7 +214,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public RoutingOutputPort HdmiOut { get; private set; } // Constructor for IBasicCommunication - public CiscoCodec(string key, string name, IBasicCommunication comm, CiscoCodecPropertiesConfig props ) + public CiscoSparkCodec(string key, string name, IBasicCommunication comm, CiscoSparkCodecPropertiesConfig props ) : base(key, name) { StandbyIsOnFeedback = new BoolFeedback(StandbyStateFeedbackFunc); @@ -329,6 +329,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco prefix + "/Status/RoomAnalytics" + Delimiter + prefix + "/Status/Standby" + Delimiter + prefix + "/Status/Video/Selfview" + Delimiter + + prefix + "/Status/Video/Layout" + Delimiter + prefix + "/Bookings" + Delimiter + prefix + "/Event/CallDisconnect" + Delimiter; @@ -675,9 +676,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco JsonConvert.PopulateObject(response, codecBookings); - CodecSchedule.Meetings = CiscoCodecBookings.GetGenericMeetingsFromBookingResult(codecBookings.CommandResponse.BookingsListResult.Booking); + if(codecBookings.CommandResponse.BookingsListResult.ResultInfo.TotalRows.Value != "0") + CodecSchedule.Meetings = CiscoCodecBookings.GetGenericMeetingsFromBookingResult(codecBookings.CommandResponse.BookingsListResult.Booking); - } } @@ -795,7 +796,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco /// public void GetDirectoryFolderContents(string folderId) { - SendText(string.Format("xCommand Phonebook Search FolderId: {0} PhonebookType: {1} ContactType: Contact Limit: {2}", folderId, PhonebookMode, PhonebookResultsLimit)); + SendText(string.Format("xCommand Phonebook Search FolderId: {0} PhonebookType: {1} ContactType: Any Limit: {2}", folderId, PhonebookMode, PhonebookResultsLimit)); } void PrintPhonebook(CodecDirectory directory) @@ -808,7 +809,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { if (item is DirectoryFolder) { - Debug.Console(1, this, "+ {0}", item.Name); + Debug.Console(1, this, "[+] {0}", item.Name); } else if (item is DirectoryContact) { @@ -818,14 +819,38 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } } - public override void Dial(string s) + /// + /// Simple dial method + /// + /// + public override void Dial(string number) { - SendText(string.Format("xCommand Dial Number: \"{0}\"", s)); + SendText(string.Format("xCommand Dial Number: \"{0}\"", number)); } - public void DialBookingId(string s) + /// + /// Dials a specific meeting + /// + /// + public override void Dial(Meeting meeting) { - SendText(string.Format("xCommand Dial BookingId: {0}", s)); + foreach (Call c in meeting.Calls) + { + Dial(c.Number, c.Protocol, c.CallRate, c.CallType, meeting.Id); + } + } + + /// + /// Detailed dial method + /// + /// + /// + /// + /// + /// + public void Dial(string number, string protocol, string callRate, string callType, string meetingId) + { + SendText(string.Format("xCommand Dial Number: \"{0}\" Protocol: {1} CallRate: {2} CallType: {3} BookingId: {4}", number, protocol, callRate, callType, meetingId)); } public override void EndCall(CodecActiveCallItem activeCall) @@ -1259,98 +1284,4 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } } - /// - /// Used to track the status of syncronizing the phonebook values when connecting to a codec or refreshing the phonebook info - /// - public class CodecPhonebookSyncState : IKeyed - { - bool _InitialSyncComplete; - - public event EventHandler InitialSyncCompleted; - - public string Key { get; private set; } - - public bool InitialSyncComplete - { - get { return _InitialSyncComplete; } - private set - { - if (value == true) - { - var handler = InitialSyncCompleted; - if (handler != null) - handler(this, new EventArgs()); - } - _InitialSyncComplete = value; - } - } - - public bool InitialPhonebookFoldersWasReceived { get; private set; } - - public bool NumberOfContactsWasReceived { get; private set; } - - public bool PhonebookRootEntriesWasRecieved { get; private set; } - - public bool PhonebookHasFolders { get; private set; } - - public int NumberOfContacts { get; private set; } - - public CodecPhonebookSyncState(string key) - { - Key = key; - - CodecDisconnected(); - } - - public void InitialPhonebookFoldersReceived() - { - InitialPhonebookFoldersWasReceived = true; - - CheckSyncStatus(); - } - - public void PhonebookRootEntriesReceived() - { - PhonebookRootEntriesWasRecieved = true; - - CheckSyncStatus(); - } - - public void SetPhonebookHasFolders(bool value) - { - PhonebookHasFolders = value; - - Debug.Console(1, this, "Phonebook has folders: {0}", PhonebookHasFolders); - } - - public void SetNumberOfContacts(int contacts) - { - NumberOfContacts = contacts; - NumberOfContactsWasReceived = true; - - Debug.Console(1, this, "Phonebook contains {0} contacts.", NumberOfContacts); - - CheckSyncStatus(); - } - - public void CodecDisconnected() - { - InitialPhonebookFoldersWasReceived = false; - PhonebookHasFolders = false; - NumberOfContacts = 0; - NumberOfContactsWasReceived = false; - } - - void CheckSyncStatus() - { - if (InitialPhonebookFoldersWasReceived && NumberOfContactsWasReceived && PhonebookRootEntriesWasRecieved) - { - InitialSyncComplete = true; - Debug.Console(1, this, "Initial Phonebook Sync Complete!"); - } - else - InitialSyncComplete = false; - } - } - } \ No newline at end of file diff --git a/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecPropertiesConfig.cs b/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs similarity index 89% rename from Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecPropertiesConfig.cs rename to Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs index 5e1b88c4..7ce5d90c 100644 --- a/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoCodecPropertiesConfig.cs +++ b/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs @@ -9,7 +9,7 @@ using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.Codec { - public class CiscoCodecPropertiesConfig + public class CiscoSparkCodecPropertiesConfig { public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } diff --git a/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/PhonebookDataClasses.cs b/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/PhonebookDataClasses.cs index edd89cbc..9a3c0ff8 100644 --- a/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/PhonebookDataClasses.cs +++ b/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/PhonebookDataClasses.cs @@ -278,6 +278,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// Converts data returned from a cisco codec to the generic Directory format. /// /// + /// /// public static CodecDirectory ConvertCiscoPhonebookToGeneric(PhonebookSearchResult result) { diff --git a/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs b/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs index fb9deeeb..24441891 100644 --- a/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs +++ b/Essentials Devices Common/Essentials Devices Common/VideoCodec/MockVC/MockVC.cs @@ -1,401 +1,406 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Routing; -using PepperDash.Essentials.Devices.Common.Codec; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec -{ - public class MockVC : VideoCodecBase, IRoutingSource, IHasCallHistory, IHasScheduleAwareness, IHasCallFavorites - { - public RoutingInputPort CodecOsdIn { get; private set; } - public RoutingInputPort HdmiIn1 { get; private set; } - public RoutingInputPort HdmiIn2 { get; private set; } - public RoutingOutputPort HdmiOut { get; private set; } - - public CodecCallFavorites CallFavorites { get; private set; } - - /// - /// - /// - public MockVC(string key, string name, MockVcPropertiesConfig props) - : base(key, name) - { - CodecInfo = new MockCodecInfo(); - - // Get favoritesw - if (props.Favorites != null) - { - CallFavorites = new CodecCallFavorites(); - CallFavorites.Favorites = props.Favorites; - } - - // Debug helpers - IncomingCallFeedback.OutputChange += (o, a) => Debug.Console(1, this, "IncomingCall={0}", _IncomingCall); - MuteFeedback.OutputChange += (o, a) => Debug.Console(1, this, "Mute={0}", _IsMuted); - PrivacyModeIsOnFeedback.OutputChange += (o, a) => Debug.Console(1, this, "Privacy={0}", _PrivacyModeIsOn); - SharingSourceFeedback.OutputChange += (o, a) => Debug.Console(1, this, "SharingSource={0}", _SharingSource); - VolumeLevelFeedback.OutputChange += (o, a) => Debug.Console(1, this, "Volume={0}", _VolumeLevel); - - CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, 0, this); - HdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, 1, this); - HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, 2, this); - HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); - - InputPorts.Add(CodecOsdIn); - InputPorts.Add(HdmiIn1); - InputPorts.Add(HdmiIn2); - OutputPorts.Add(HdmiOut); - - CallHistory = new CodecCallHistory(); - for (int i = 0; i < 10; i++) - { - var call = new CodecCallHistory.CallHistoryEntry(); - call.Name = "Call " + i; - call.Number = i + "@call.com"; - CallHistory.RecentCalls.Add(call); - } - // eventually fire history event here - - SetIsReady(); - } - - protected override Func IncomingCallFeedbackFunc - { - get { return () => _IncomingCall; } - } - bool _IncomingCall; - - protected override Func MuteFeedbackFunc - { - get { return () => _IsMuted; } - } - bool _IsMuted; - - protected override Func PrivacyModeIsOnFeedbackFunc - { - get { return () => _PrivacyModeIsOn; } - } - bool _PrivacyModeIsOn; - - protected override Func SharingSourceFeedbackFunc - { - get { return () => _SharingSource; } - } - string _SharingSource; - - protected override Func VolumeLevelFeedbackFunc - { - get { return () => _VolumeLevel; } - } - int _VolumeLevel; - - /// - /// Dials, yo! - /// - public override void Dial(string s) - { - Debug.Console(1, this, "Dial: {0}", s); - var call = new CodecActiveCallItem() { Name = s, Number = s, Id = s, Status = eCodecCallStatus.Dialing }; - ActiveCalls.Add(call); - OnCallStatusChange(eCodecCallStatus.Unknown, call.Status, call); - //ActiveCallCountFeedback.FireUpdate(); - // Simulate 2-second ring, then connecting, then connected - new CTimer(o => - { - call.Type = eCodecCallType.Video; - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); - new CTimer(oo => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); - }, 2000); - } - - /// - /// - /// - public override void EndCall(CodecActiveCallItem call) - { - Debug.Console(1, this, "EndCall"); - ActiveCalls.Remove(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); - //ActiveCallCountFeedback.FireUpdate(); - } - - /// - /// - /// - public override void EndAllCalls() - { - Debug.Console(1, this, "EndAllCalls"); - for(int i = ActiveCalls.Count - 1; i >= 0; i--) - { - var call = ActiveCalls[i]; - ActiveCalls.Remove(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); - } - //ActiveCallCountFeedback.FireUpdate(); - } - - /// - /// For a call from the test methods below - /// - public override void AcceptCall(CodecActiveCallItem call) - { - Debug.Console(1, this, "AcceptCall"); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); - new CTimer(o => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); - // should already be in active list - } - - /// - /// For a call from the test methods below - /// - public override void RejectCall(CodecActiveCallItem call) - { - Debug.Console(1, this, "RejectCall"); - ActiveCalls.Remove(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); - //ActiveCallCountFeedback.FireUpdate(); - } - - /// - /// Makes horrible tones go out on the wire! - /// - /// - public override void SendDtmf(string s) - { - Debug.Console(1, this, "SendDTMF: {0}", s); - } - - /// - /// - /// - public override void StartSharing() - { - } - - /// - /// - /// - public override void StopSharing() - { - } - - /// - /// Called by routing to make it happen - /// - /// - public override void ExecuteSwitch(object selector) - { - Debug.Console(1, this, "ExecuteSwitch: {0}", selector); - _SharingSource = selector.ToString(); - } - - /// - /// - /// - public override void MuteOff() - { - _IsMuted = false; - MuteFeedback.FireUpdate(); - } - - /// - /// - /// - public override void MuteOn() - { - _IsMuted = true; - MuteFeedback.FireUpdate(); - } - - /// - /// - /// - public override void MuteToggle() - { - _IsMuted = !_IsMuted; - MuteFeedback.FireUpdate(); - } - - /// - /// - /// - /// - public override void SetVolume(ushort level) - { - _VolumeLevel = level; - VolumeLevelFeedback.FireUpdate(); - } - - /// - /// - /// - /// - public override void VolumeDown(bool pressRelease) - { - } - - /// - /// - /// - /// - public override void VolumeUp(bool pressRelease) - { - } - - /// - /// - /// - public override void PrivacyModeOn() - { - Debug.Console(1, this, "PrivacyMuteOn"); - if (_PrivacyModeIsOn) - return; - _PrivacyModeIsOn = true; - PrivacyModeIsOnFeedback.FireUpdate(); - } - - /// - /// - /// - public override void PrivacyModeOff() - { - Debug.Console(1, this, "PrivacyMuteOff"); - if (!_PrivacyModeIsOn) - return; - _PrivacyModeIsOn = false; - PrivacyModeIsOnFeedback.FireUpdate(); - } - - /// - /// - /// - public override void PrivacyModeToggle() - { - _PrivacyModeIsOn = !_PrivacyModeIsOn; - Debug.Console(1, this, "PrivacyMuteToggle: {0}", _PrivacyModeIsOn); - PrivacyModeIsOnFeedback.FireUpdate(); - } - - //******************************************************** - // SIMULATION METHODS - - /// - /// - /// - /// - public void TestIncomingVideoCall(string url) - { - Debug.Console(1, this, "TestIncomingVideoCall from {0}", url); - var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type= eCodecCallType.Video, Direction = eCodecCallDirection.Incoming }; - ActiveCalls.Add(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); - _IncomingCall = true; - IncomingCallFeedback.FireUpdate(); - } - - /// - /// - /// - /// - public void TestIncomingAudioCall(string url) - { - Debug.Console(1, this, "TestIncomingAudioCall from {0}", url); - var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type = eCodecCallType.Audio, Direction = eCodecCallDirection.Incoming }; - ActiveCalls.Add(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); - _IncomingCall = true; - IncomingCallFeedback.FireUpdate(); - } - - /// - /// - /// - public void TestFarEndHangup() - { - Debug.Console(1, this, "TestFarEndHangup"); - - } - - #region IHasCallHistory Members - - public CodecCallHistory CallHistory { get; private set; } - - public void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry) - { - - } - - #endregion - - #region IHasScheduleAwareness Members - - public CodecScheduleAwareness CodecSchedule - { - get { - // if the last meeting has past, generate a new list - if (_CodecSchedule == null - || _CodecSchedule.Meetings[_CodecSchedule.Meetings.Count - 1].StartTime < DateTime.Now) - { - _CodecSchedule = new CodecScheduleAwareness(); - for (int i = 0; i < 5; i++) - { - var m = new Meeting(); - m.StartTime = DateTime.Now.AddMinutes(3).AddHours(i); - m.EndTime = DateTime.Now.AddHours(i).AddMinutes(30); - m.Title = "Meeting " + i; - m.ConferenceNumberToDial = i + "meeting@fake.com"; - _CodecSchedule.Meetings.Add(m); - } - } - return _CodecSchedule; - } - } - CodecScheduleAwareness _CodecSchedule; - - #endregion - } - - /// - /// Implementation for the mock VC - /// - public class MockCodecInfo : VideoCodecInfo - { - - public override bool MultiSiteOptionIsEnabled - { - get { return true; } - } - - public override string IpAddress - { - get { return "xx.xx.xx.xx"; } - } - - public override string PhoneNumber - { - get { return "333-444-5555"; } - } - - public override string SipUri - { - get { return "mock@someurl.com"; } - } - - public override bool AutoAnswerEnabled - { - get { return _AutoAnswerEnabled; } - } - bool _AutoAnswerEnabled; - - public void SetAutoAnswer(bool value) - { - _AutoAnswerEnabled = value; - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Routing; +using PepperDash.Essentials.Devices.Common.Codec; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec +{ + public class MockVC : VideoCodecBase, IRoutingSource, IHasCallHistory, IHasScheduleAwareness, IHasCallFavorites + { + public RoutingInputPort CodecOsdIn { get; private set; } + public RoutingInputPort HdmiIn1 { get; private set; } + public RoutingInputPort HdmiIn2 { get; private set; } + public RoutingOutputPort HdmiOut { get; private set; } + + public CodecCallFavorites CallFavorites { get; private set; } + + /// + /// + /// + public MockVC(string key, string name, MockVcPropertiesConfig props) + : base(key, name) + { + CodecInfo = new MockCodecInfo(); + + // Get favoritesw + if (props.Favorites != null) + { + CallFavorites = new CodecCallFavorites(); + CallFavorites.Favorites = props.Favorites; + } + + // Debug helpers + IncomingCallFeedback.OutputChange += (o, a) => Debug.Console(1, this, "IncomingCall={0}", _IncomingCall); + MuteFeedback.OutputChange += (o, a) => Debug.Console(1, this, "Mute={0}", _IsMuted); + PrivacyModeIsOnFeedback.OutputChange += (o, a) => Debug.Console(1, this, "Privacy={0}", _PrivacyModeIsOn); + SharingSourceFeedback.OutputChange += (o, a) => Debug.Console(1, this, "SharingSource={0}", _SharingSource); + VolumeLevelFeedback.OutputChange += (o, a) => Debug.Console(1, this, "Volume={0}", _VolumeLevel); + + CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, 0, this); + HdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, 1, this); + HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, 2, this); + HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); + + InputPorts.Add(CodecOsdIn); + InputPorts.Add(HdmiIn1); + InputPorts.Add(HdmiIn2); + OutputPorts.Add(HdmiOut); + + CallHistory = new CodecCallHistory(); + for (int i = 0; i < 10; i++) + { + var call = new CodecCallHistory.CallHistoryEntry(); + call.Name = "Call " + i; + call.Number = i + "@call.com"; + CallHistory.RecentCalls.Add(call); + } + // eventually fire history event here + + SetIsReady(); + } + + protected override Func IncomingCallFeedbackFunc + { + get { return () => _IncomingCall; } + } + bool _IncomingCall; + + protected override Func MuteFeedbackFunc + { + get { return () => _IsMuted; } + } + bool _IsMuted; + + protected override Func PrivacyModeIsOnFeedbackFunc + { + get { return () => _PrivacyModeIsOn; } + } + bool _PrivacyModeIsOn; + + protected override Func SharingSourceFeedbackFunc + { + get { return () => _SharingSource; } + } + string _SharingSource; + + protected override Func VolumeLevelFeedbackFunc + { + get { return () => _VolumeLevel; } + } + int _VolumeLevel; + + /// + /// Dials, yo! + /// + public override void Dial(string number) + { + Debug.Console(1, this, "Dial: {0}", number); + var call = new CodecActiveCallItem() { Name = number, Number = number, Id = number, Status = eCodecCallStatus.Dialing }; + ActiveCalls.Add(call); + OnCallStatusChange(eCodecCallStatus.Unknown, call.Status, call); + //ActiveCallCountFeedback.FireUpdate(); + // Simulate 2-second ring, then connecting, then connected + new CTimer(o => + { + call.Type = eCodecCallType.Video; + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); + new CTimer(oo => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); + }, 2000); + } + + public override void Dial(Meeting meeting) + { + throw new NotImplementedException(); + } + + /// + /// + /// + public override void EndCall(CodecActiveCallItem call) + { + Debug.Console(1, this, "EndCall"); + ActiveCalls.Remove(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); + //ActiveCallCountFeedback.FireUpdate(); + } + + /// + /// + /// + public override void EndAllCalls() + { + Debug.Console(1, this, "EndAllCalls"); + for(int i = ActiveCalls.Count - 1; i >= 0; i--) + { + var call = ActiveCalls[i]; + ActiveCalls.Remove(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); + } + //ActiveCallCountFeedback.FireUpdate(); + } + + /// + /// For a call from the test methods below + /// + public override void AcceptCall(CodecActiveCallItem call) + { + Debug.Console(1, this, "AcceptCall"); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); + new CTimer(o => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); + // should already be in active list + } + + /// + /// For a call from the test methods below + /// + public override void RejectCall(CodecActiveCallItem call) + { + Debug.Console(1, this, "RejectCall"); + ActiveCalls.Remove(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); + //ActiveCallCountFeedback.FireUpdate(); + } + + /// + /// Makes horrible tones go out on the wire! + /// + /// + public override void SendDtmf(string s) + { + Debug.Console(1, this, "SendDTMF: {0}", s); + } + + /// + /// + /// + public override void StartSharing() + { + } + + /// + /// + /// + public override void StopSharing() + { + } + + /// + /// Called by routing to make it happen + /// + /// + public override void ExecuteSwitch(object selector) + { + Debug.Console(1, this, "ExecuteSwitch: {0}", selector); + _SharingSource = selector.ToString(); + } + + /// + /// + /// + public override void MuteOff() + { + _IsMuted = false; + MuteFeedback.FireUpdate(); + } + + /// + /// + /// + public override void MuteOn() + { + _IsMuted = true; + MuteFeedback.FireUpdate(); + } + + /// + /// + /// + public override void MuteToggle() + { + _IsMuted = !_IsMuted; + MuteFeedback.FireUpdate(); + } + + /// + /// + /// + /// + public override void SetVolume(ushort level) + { + _VolumeLevel = level; + VolumeLevelFeedback.FireUpdate(); + } + + /// + /// + /// + /// + public override void VolumeDown(bool pressRelease) + { + } + + /// + /// + /// + /// + public override void VolumeUp(bool pressRelease) + { + } + + /// + /// + /// + public override void PrivacyModeOn() + { + Debug.Console(1, this, "PrivacyMuteOn"); + if (_PrivacyModeIsOn) + return; + _PrivacyModeIsOn = true; + PrivacyModeIsOnFeedback.FireUpdate(); + } + + /// + /// + /// + public override void PrivacyModeOff() + { + Debug.Console(1, this, "PrivacyMuteOff"); + if (!_PrivacyModeIsOn) + return; + _PrivacyModeIsOn = false; + PrivacyModeIsOnFeedback.FireUpdate(); + } + + /// + /// + /// + public override void PrivacyModeToggle() + { + _PrivacyModeIsOn = !_PrivacyModeIsOn; + Debug.Console(1, this, "PrivacyMuteToggle: {0}", _PrivacyModeIsOn); + PrivacyModeIsOnFeedback.FireUpdate(); + } + + //******************************************************** + // SIMULATION METHODS + + /// + /// + /// + /// + public void TestIncomingVideoCall(string url) + { + Debug.Console(1, this, "TestIncomingVideoCall from {0}", url); + var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type= eCodecCallType.Video, Direction = eCodecCallDirection.Incoming }; + ActiveCalls.Add(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); + _IncomingCall = true; + IncomingCallFeedback.FireUpdate(); + } + + /// + /// + /// + /// + public void TestIncomingAudioCall(string url) + { + Debug.Console(1, this, "TestIncomingAudioCall from {0}", url); + var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type = eCodecCallType.Audio, Direction = eCodecCallDirection.Incoming }; + ActiveCalls.Add(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); + _IncomingCall = true; + IncomingCallFeedback.FireUpdate(); + } + + /// + /// + /// + public void TestFarEndHangup() + { + Debug.Console(1, this, "TestFarEndHangup"); + + } + + #region IHasCallHistory Members + + public CodecCallHistory CallHistory { get; private set; } + + public void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry) + { + + } + + #endregion + + #region IHasScheduleAwareness Members + + public CodecScheduleAwareness CodecSchedule + { + get { + // if the last meeting has past, generate a new list + if (_CodecSchedule == null + || _CodecSchedule.Meetings[_CodecSchedule.Meetings.Count - 1].StartTime < DateTime.Now) + { + _CodecSchedule = new CodecScheduleAwareness(); + for (int i = 0; i < 5; i++) + { + var m = new Meeting(); + m.StartTime = DateTime.Now.AddMinutes(3).AddHours(i); + m.EndTime = DateTime.Now.AddHours(i).AddMinutes(30); + m.Title = "Meeting " + i; + m.Calls[0].Number = i + "meeting@fake.com"; + _CodecSchedule.Meetings.Add(m); + } + } + return _CodecSchedule; + } + } + CodecScheduleAwareness _CodecSchedule; + + #endregion + } + + /// + /// Implementation for the mock VC + /// + public class MockCodecInfo : VideoCodecInfo + { + + public override bool MultiSiteOptionIsEnabled + { + get { return true; } + } + + public override string IpAddress + { + get { return "xx.xx.xx.xx"; } + } + + public override string PhoneNumber + { + get { return "333-444-5555"; } + } + + public override string SipUri + { + get { return "mock@someurl.com"; } + } + + public override bool AutoAnswerEnabled + { + get { return _AutoAnswerEnabled; } + } + bool _AutoAnswerEnabled; + + public void SetAutoAnswer(bool value) + { + _AutoAnswerEnabled = value; + } + } } \ No newline at end of file diff --git a/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index feee31bc..a72b713d 100644 --- a/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -65,13 +65,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); - + ActiveCalls = new List(); } #region IHasDialer Members - public abstract void Dial(string s); + public abstract void Dial(string number); + public abstract void Dial(Meeting meeting); public abstract void EndCall(CodecActiveCallItem call); public abstract void EndAllCalls(); public abstract void AcceptCall(CodecActiveCallItem call); @@ -198,4 +199,98 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec CallItem = item; } } + + /// + /// Used to track the status of syncronizing the phonebook values when connecting to a codec or refreshing the phonebook info + /// + public class CodecPhonebookSyncState : IKeyed + { + bool _InitialSyncComplete; + + public event EventHandler InitialSyncCompleted; + + public string Key { get; private set; } + + public bool InitialSyncComplete + { + get { return _InitialSyncComplete; } + private set + { + if (value == true) + { + var handler = InitialSyncCompleted; + if (handler != null) + handler(this, new EventArgs()); + } + _InitialSyncComplete = value; + } + } + + public bool InitialPhonebookFoldersWasReceived { get; private set; } + + public bool NumberOfContactsWasReceived { get; private set; } + + public bool PhonebookRootEntriesWasRecieved { get; private set; } + + public bool PhonebookHasFolders { get; private set; } + + public int NumberOfContacts { get; private set; } + + public CodecPhonebookSyncState(string key) + { + Key = key; + + CodecDisconnected(); + } + + public void InitialPhonebookFoldersReceived() + { + InitialPhonebookFoldersWasReceived = true; + + CheckSyncStatus(); + } + + public void PhonebookRootEntriesReceived() + { + PhonebookRootEntriesWasRecieved = true; + + CheckSyncStatus(); + } + + public void SetPhonebookHasFolders(bool value) + { + PhonebookHasFolders = value; + + Debug.Console(1, this, "Phonebook has folders: {0}", PhonebookHasFolders); + } + + public void SetNumberOfContacts(int contacts) + { + NumberOfContacts = contacts; + NumberOfContactsWasReceived = true; + + Debug.Console(1, this, "Phonebook contains {0} contacts.", NumberOfContacts); + + CheckSyncStatus(); + } + + public void CodecDisconnected() + { + InitialPhonebookFoldersWasReceived = false; + PhonebookHasFolders = false; + NumberOfContacts = 0; + NumberOfContactsWasReceived = false; + } + + void CheckSyncStatus() + { + if (InitialPhonebookFoldersWasReceived && NumberOfContactsWasReceived && PhonebookRootEntriesWasRecieved) + { + InitialSyncComplete = true; + Debug.Console(1, this, "Initial Phonebook Sync Complete!"); + } + else + InitialSyncComplete = false; + } + } } \ No newline at end of file diff --git a/Essentials/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs b/Essentials/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs index c784f91a..3f768188 100644 --- a/Essentials/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs +++ b/Essentials/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs @@ -1,437 +1,437 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Room.Config; - -namespace PepperDash.Essentials -{ - public class EssentialsPresentationRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange - { - public event EventHandler CurrentVolumeDeviceChange; - public event SourceInfoChangeHandler CurrentSingleSourceChange; - public event SourceInfoChangeHandler CurrentDisplay1SourceChange; - public event SourceInfoChangeHandler CurrentDisplay2SourceChange; - - protected override Func OnFeedbackFunc { get { - return () => (CurrentSingleSourceInfo != null - && CurrentSingleSourceInfo.Type != eSourceListItemType.Off) - || (Display1SourceInfo != null - && Display1SourceInfo.Type != eSourceListItemType.Off) - || (Display2SourceInfo != null - && Display2SourceInfo.Type != eSourceListItemType.Off); } } - - protected override Func IsWarmingFeedbackFunc { get { return () =>false;; } } - protected override Func IsCoolingFeedbackFunc { get { return () => false; } } - - public EssentialsPresentationRoomPropertiesConfig Config { get; private set; } - - public Dictionary Displays { get; private set; } - - public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; } - public IBasicVolumeControls DefaultVolumeControls { get; private set; } - - /// - /// The config name of the source list - /// - public string SourceListKey { get; set; } - - /// - /// If room is off, enables power on to last source. Default true - /// - public bool EnablePowerOnToLastSource { get; set; } - string LastSourceKey; - - public enum eVideoRoutingMode - { - SelectSourceSelectDisplay, SourceToAllDisplays - } - - public eVideoRoutingMode VideoRoutingMode { get; set; } - - public enum eAudioRoutingMode - { - AudioFollowsLastVideo, SelectAudioFromDisplay - } - - /// - /// - /// - public IBasicVolumeControls CurrentVolumeControls - { - get { return _CurrentAudioDevice; } - set - { - if (value == _CurrentAudioDevice) return; - - var oldDev = _CurrentAudioDevice; - // derigister this room from the device, if it can - if (oldDev is IInUseTracking) - (oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio"); - var handler = CurrentVolumeDeviceChange; - if (handler != null) - CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange)); - _CurrentAudioDevice = value; - if (handler != null) - CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange)); - // register this room with new device, if it can - if (_CurrentAudioDevice is IInUseTracking) - (_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio"); - } - } - IBasicVolumeControls _CurrentAudioDevice; - - /// - /// The SourceListItem last run - containing names and icons. The complex setter is - /// to add/remove this room to the source's InUseTracking, if it is capable - /// - public SourceListItem CurrentSingleSourceInfo - { - get { return _CurrentSingleSourceInfo; } - private set - { - if (value == _CurrentSingleSourceInfo) return; - - var handler = CurrentSingleSourceChange; - // remove from in-use tracker, if so equipped - if(_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking) - (_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control"); - - if (handler != null) - handler(this, _CurrentSingleSourceInfo, ChangeType.WillChange); - - _CurrentSingleSourceInfo = value; - - // add to in-use tracking - if (_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking) - (_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control"); - if (handler != null) - handler(this, _CurrentSingleSourceInfo, ChangeType.DidChange); - } - } - SourceListItem _CurrentSingleSourceInfo; - - public SourceListItem Display1SourceInfo - { - get { return _Display1SourceInfo; } - set - { - if (value == _Display1SourceInfo) return; - - var handler = CurrentDisplay1SourceChange; - if (handler != null) - handler(this, _Display1SourceInfo, ChangeType.WillChange); - - _Display1SourceInfo = value; - - if (handler != null) - handler(this, _Display1SourceInfo, ChangeType.DidChange); - } - } - SourceListItem _Display1SourceInfo; - - public SourceListItem Display2SourceInfo - { - get { return _Display2SourceInfo; } - set - { - if (value == _Display2SourceInfo) return; - - var handler = CurrentDisplay2SourceChange; - if (handler != null) - handler(this, _Display2SourceInfo, ChangeType.WillChange); - - _Display2SourceInfo = value; - - if (handler != null) - handler(this, _Display2SourceInfo, ChangeType.DidChange); - } - } - SourceListItem _Display2SourceInfo; - - /// - /// If an audio dialer is available for this room - /// - public bool HasAudioDialer { get { return false; } } - /// - /// - /// - /// - /// - public EssentialsPresentationRoom(string key, string name, - Dictionary displays, - IBasicVolumeWithFeedback defaultVolume, EssentialsPresentationRoomPropertiesConfig config) - : base(key, name) - { - Config = config; - Displays = displays; - - DefaultVolumeControls = defaultVolume; - CurrentVolumeControls = defaultVolume; - - //DefaultAudioDevice = defaultAudio; - //if (defaultAudio is IBasicVolumeControls) - // DefaultVolumeControls = defaultAudio as IBasicVolumeControls; - //else if (defaultAudio is IHasVolumeDevice) - // DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice; - - - SourceListKey = "default"; - EnablePowerOnToLastSource = true; - } - - /// - /// Run the same source to all destinations - /// - /// - public void RouteSourceToAllDestinations(SourceListItem sourceItem) - { - if (Config.Volumes.Master != null) - { - var audioDev = DeviceManager.GetDeviceForKey(Config.Volumes.Master.DeviceKey); - if (audioDev is IBasicVolumeWithFeedback) - { - - } - } - - foreach (var display in Displays.Values) - { - if (sourceItem != null) - DoVideoRoute(sourceItem.SourceKey, display.Key); - else - DoVideoRoute("$off", display.Key); - } - Display1SourceInfo = sourceItem; - Display2SourceInfo = sourceItem; - CurrentSingleSourceInfo = sourceItem; - OnFeedback.FireUpdate(); - } - - public void SourceToDisplay1(SourceListItem sourceItem) - { - DoVideoRoute(sourceItem.SourceKey, Displays[1].Key); - Display1SourceInfo = sourceItem; - OnFeedback.FireUpdate(); - } - - public void SourceToDisplay2(SourceListItem sourceItem) - { - DoVideoRoute(sourceItem.SourceKey, Displays[2].Key); - Display2SourceInfo = sourceItem; - OnFeedback.FireUpdate(); - } - - - /// - /// Basic source -> destination routing - /// - void DoVideoRoute(string sourceKey, string destinationKey) - { - new CTimer(o => - { - var dest = DeviceManager.GetDeviceForKey(destinationKey) as IRoutingSinkNoSwitching; - if (dest == null) - { - Debug.Console(1, this, "Cannot route. Destination '{0}' not found", destinationKey); - return; - } - // off is special case - if (sourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) - { - dest.ReleaseRoute(); - if (dest is IPower) - (dest as IPower).PowerOff(); - return; - } - - var source = DeviceManager.GetDeviceForKey(sourceKey) as IRoutingOutputs; - if (source == null) - { - Debug.Console(1, this, "Cannot route. Source '{0}' not found", sourceKey); - return; - } - dest.ReleaseAndMakeRoute(source, eRoutingSignalType.Video); - }, 0); - } - - /// - /// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Room.Config; + +namespace PepperDash.Essentials +{ + public class EssentialsPresentationRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange + { + public event EventHandler CurrentVolumeDeviceChange; + public event SourceInfoChangeHandler CurrentSingleSourceChange; + public event SourceInfoChangeHandler CurrentDisplay1SourceChange; + public event SourceInfoChangeHandler CurrentDisplay2SourceChange; + + protected override Func OnFeedbackFunc { get { + return () => (CurrentSingleSourceInfo != null + && CurrentSingleSourceInfo.Type != eSourceListItemType.Off) + || (Display1SourceInfo != null + && Display1SourceInfo.Type != eSourceListItemType.Off) + || (Display2SourceInfo != null + && Display2SourceInfo.Type != eSourceListItemType.Off); } } + + protected override Func IsWarmingFeedbackFunc { get { return () =>false;; } } + protected override Func IsCoolingFeedbackFunc { get { return () => false; } } + + public EssentialsPresentationRoomPropertiesConfig Config { get; private set; } + + public Dictionary Displays { get; private set; } + + public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; } + public IBasicVolumeControls DefaultVolumeControls { get; private set; } + + /// + /// The config name of the source list + /// + public string SourceListKey { get; set; } + + /// + /// If room is off, enables power on to last source. Default true + /// + public bool EnablePowerOnToLastSource { get; set; } + string LastSourceKey; + + public enum eVideoRoutingMode + { + SelectSourceSelectDisplay, SourceToAllDisplays + } + + public eVideoRoutingMode VideoRoutingMode { get; set; } + + public enum eAudioRoutingMode + { + AudioFollowsLastVideo, SelectAudioFromDisplay + } + + /// + /// + /// + public IBasicVolumeControls CurrentVolumeControls + { + get { return _CurrentAudioDevice; } + set + { + if (value == _CurrentAudioDevice) return; + + var oldDev = _CurrentAudioDevice; + // derigister this room from the device, if it can + if (oldDev is IInUseTracking) + (oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio"); + var handler = CurrentVolumeDeviceChange; + if (handler != null) + CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange)); + _CurrentAudioDevice = value; + if (handler != null) + CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange)); + // register this room with new device, if it can + if (_CurrentAudioDevice is IInUseTracking) + (_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio"); + } + } + IBasicVolumeControls _CurrentAudioDevice; + + /// + /// The SourceListItem last run - containing names and icons. The complex setter is + /// to add/remove this room to the source's InUseTracking, if it is capable + /// + public SourceListItem CurrentSingleSourceInfo + { + get { return _CurrentSingleSourceInfo; } + private set + { + if (value == _CurrentSingleSourceInfo) return; + + var handler = CurrentSingleSourceChange; + // remove from in-use tracker, if so equipped + if(_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking) + (_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control"); + + if (handler != null) + handler(this, _CurrentSingleSourceInfo, ChangeType.WillChange); + + _CurrentSingleSourceInfo = value; + + // add to in-use tracking + if (_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking) + (_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control"); + if (handler != null) + handler(this, _CurrentSingleSourceInfo, ChangeType.DidChange); + } + } + SourceListItem _CurrentSingleSourceInfo; + + public SourceListItem Display1SourceInfo + { + get { return _Display1SourceInfo; } + set + { + if (value == _Display1SourceInfo) return; + + var handler = CurrentDisplay1SourceChange; + if (handler != null) + handler(this, _Display1SourceInfo, ChangeType.WillChange); + + _Display1SourceInfo = value; + + if (handler != null) + handler(this, _Display1SourceInfo, ChangeType.DidChange); + } + } + SourceListItem _Display1SourceInfo; + + public SourceListItem Display2SourceInfo + { + get { return _Display2SourceInfo; } + set + { + if (value == _Display2SourceInfo) return; + + var handler = CurrentDisplay2SourceChange; + if (handler != null) + handler(this, _Display2SourceInfo, ChangeType.WillChange); + + _Display2SourceInfo = value; + + if (handler != null) + handler(this, _Display2SourceInfo, ChangeType.DidChange); + } + } + SourceListItem _Display2SourceInfo; + + /// + /// If an audio dialer is available for this room /// - protected override void EndShutdown() - { - RunRouteAction("roomoff"); - } - - /// - /// - /// - /// - public void RunRouteAction(string routeKey) - { - RunRouteAction(routeKey, null); - } - - /// - /// Gets a source from config list SourceListKey and dynamically build and executes the - /// route or commands - /// - /// - public void RunRouteAction(string routeKey, Action successCallback) - { - // Run this on a separate thread - new CTimer(o => - { - Debug.Console(1, this, "Run room action '{0}'", routeKey); - var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey); - if(dict == null) - { - Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey); - return; - } - - // Try to get the list item by it's string key - if (!dict.ContainsKey(routeKey)) - { - Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'", - routeKey, SourceListKey); - return; - } - - var item = dict[routeKey]; - //Debug.Console(2, this, "Action {0} has {1} steps", - // item.SourceKey, item.RouteList.Count); - - // Let's run it - if (routeKey.ToLower() != "roomoff") - LastSourceKey = routeKey; - - foreach (var route in item.RouteList) - { - // if there is a $defaultAll on route, run two separate - if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase)) - { - var tempAudio = new SourceRouteListItem - { - DestinationKey = "$defaultDisplay", - SourceKey = route.SourceKey, - Type = eRoutingSignalType.Video - }; - DoRoute(tempAudio); - - var tempVideo = new SourceRouteListItem - { - DestinationKey = "$defaultAudio", - SourceKey = route.SourceKey, - Type = eRoutingSignalType.Audio - }; - DoRoute(tempVideo); - continue; - } - else - DoRoute(route); - } - - // Set volume control on room, using default if non provided - IBasicVolumeControls volDev = null; - // Handle special cases for volume control - if (string.IsNullOrEmpty(item.VolumeControlKey) - || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase)) - volDev = DefaultVolumeControls; - //else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) - // volDev = DefaultDisplay as IBasicVolumeControls; - // Or a specific device, probably rarely used. - else - { - var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey); - if (dev is IBasicVolumeControls) - volDev = dev as IBasicVolumeControls; - else if (dev is IHasVolumeDevice) - volDev = (dev as IHasVolumeDevice).VolumeDevice; - } - CurrentVolumeControls = volDev; - - // store the name and UI info for routes - if (item.SourceKey != null) - CurrentSingleSourceInfo = item; - // And finally, set the "control". This will trigger event - //CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device; - - OnFeedback.FireUpdate(); - - // report back when done - if (successCallback != null) - successCallback(); - }, 0); // end of CTimer - } - - /// - /// Will power the room on with the last-used source - /// - public void PowerOnToDefaultOrLastSource() - { - if (!EnablePowerOnToLastSource || LastSourceKey == null) - return; - RunRouteAction(LastSourceKey); - } - - /// - /// Does what it says - /// - public override void SetDefaultLevels() - { - Debug.Console(0, this, "SetDefaultLevels not implemented"); - } - - /// - /// - /// - /// - /// - bool DoRoute(SourceRouteListItem route) - { - IRoutingSinkNoSwitching dest = null; - - if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase)) - dest = DefaultAudioDevice; - //else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) - // dest = DefaultDisplay; - else - dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching; - - if (dest == null) - { - Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey); - return false; - } - - if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) - { - dest.ReleaseRoute(); - if (dest is IPower) - (dest as IPower).PowerOff(); - } - else - { - var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs; - if (source == null) - { - Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey); - return false; - } - dest.ReleaseAndMakeRoute(source, route.Type); - } - return true; + public bool HasAudioDialer { get { return false; } } + /// + /// + /// + /// + /// + public EssentialsPresentationRoom(string key, string name, + Dictionary displays, + IBasicVolumeWithFeedback defaultVolume, EssentialsPresentationRoomPropertiesConfig config) + : base(key, name) + { + Config = config; + Displays = displays; + + DefaultVolumeControls = defaultVolume; + CurrentVolumeControls = defaultVolume; + + //DefaultAudioDevice = defaultAudio; + //if (defaultAudio is IBasicVolumeControls) + // DefaultVolumeControls = defaultAudio as IBasicVolumeControls; + //else if (defaultAudio is IHasVolumeDevice) + // DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice; + + + SourceListKey = "default"; + EnablePowerOnToLastSource = true; + } + + /// + /// Run the same source to all destinations + /// + /// + public void RouteSourceToAllDestinations(SourceListItem sourceItem) + { + if (Config.Volumes.Master != null) + { + var audioDev = DeviceManager.GetDeviceForKey(Config.Volumes.Master.DeviceKey); + if (audioDev is IBasicVolumeWithFeedback) + { + + } + } + + foreach (var display in Displays.Values) + { + if (sourceItem != null) + DoVideoRoute(sourceItem.SourceKey, display.Key); + else + DoVideoRoute("$off", display.Key); + } + Display1SourceInfo = sourceItem; + Display2SourceInfo = sourceItem; + CurrentSingleSourceInfo = sourceItem; + OnFeedback.FireUpdate(); + } + + public void SourceToDisplay1(SourceListItem sourceItem) + { + DoVideoRoute(sourceItem.SourceKey, Displays[1].Key); + Display1SourceInfo = sourceItem; + OnFeedback.FireUpdate(); + } + + public void SourceToDisplay2(SourceListItem sourceItem) + { + DoVideoRoute(sourceItem.SourceKey, Displays[2].Key); + Display2SourceInfo = sourceItem; + OnFeedback.FireUpdate(); + } + + + /// + /// Basic source -> destination routing + /// + void DoVideoRoute(string sourceKey, string destinationKey) + { + new CTimer(o => + { + var dest = DeviceManager.GetDeviceForKey(destinationKey) as IRoutingSinkNoSwitching; + if (dest == null) + { + Debug.Console(1, this, "Cannot route. Destination '{0}' not found", destinationKey); + return; + } + // off is special case + if (sourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) + { + dest.ReleaseRoute(); + if (dest is IPower) + (dest as IPower).PowerOff(); + return; + } + + var source = DeviceManager.GetDeviceForKey(sourceKey) as IRoutingOutputs; + if (source == null) + { + Debug.Console(1, this, "Cannot route. Source '{0}' not found", sourceKey); + return; + } + dest.ReleaseAndMakeRoute(source, eRoutingSignalType.Video); + }, 0); + } + + /// + /// + /// + protected override void EndShutdown() + { + RunRouteAction("roomoff"); + } + + /// + /// + /// + /// + public void RunRouteAction(string routeKey) + { + RunRouteAction(routeKey, null); + } + + /// + /// Gets a source from config list SourceListKey and dynamically build and executes the + /// route or commands + /// + /// + public void RunRouteAction(string routeKey, Action successCallback) + { + // Run this on a separate thread + new CTimer(o => + { + Debug.Console(1, this, "Run room action '{0}'", routeKey); + var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey); + if(dict == null) + { + Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey); + return; + } + + // Try to get the list item by it's string key + if (!dict.ContainsKey(routeKey)) + { + Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'", + routeKey, SourceListKey); + return; + } + + var item = dict[routeKey]; + //Debug.Console(2, this, "Action {0} has {1} steps", + // item.SourceKey, item.RouteList.Count); + + // Let's run it + if (routeKey.ToLower() != "roomoff") + LastSourceKey = routeKey; + + foreach (var route in item.RouteList) + { + // if there is a $defaultAll on route, run two separate + if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase)) + { + var tempAudio = new SourceRouteListItem + { + DestinationKey = "$defaultDisplay", + SourceKey = route.SourceKey, + Type = eRoutingSignalType.Video + }; + DoRoute(tempAudio); + + var tempVideo = new SourceRouteListItem + { + DestinationKey = "$defaultAudio", + SourceKey = route.SourceKey, + Type = eRoutingSignalType.Audio + }; + DoRoute(tempVideo); + continue; + } + else + DoRoute(route); + } + + // Set volume control on room, using default if non provided + IBasicVolumeControls volDev = null; + // Handle special cases for volume control + if (string.IsNullOrEmpty(item.VolumeControlKey) + || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase)) + volDev = DefaultVolumeControls; + //else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) + // volDev = DefaultDisplay as IBasicVolumeControls; + // Or a specific device, probably rarely used. + else + { + var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey); + if (dev is IBasicVolumeControls) + volDev = dev as IBasicVolumeControls; + else if (dev is IHasVolumeDevice) + volDev = (dev as IHasVolumeDevice).VolumeDevice; + } + CurrentVolumeControls = volDev; + + // store the name and UI info for routes + if (item.SourceKey != null) + CurrentSingleSourceInfo = item; + // And finally, set the "control". This will trigger event + //CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device; + + OnFeedback.FireUpdate(); + + // report back when done + if (successCallback != null) + successCallback(); + }, 0); // end of CTimer + } + + /// + /// Will power the room on with the last-used source + /// + public void PowerOnToDefaultOrLastSource() + { + if (!EnablePowerOnToLastSource || LastSourceKey == null) + return; + RunRouteAction(LastSourceKey); + } + + /// + /// Does what it says + /// + public override void SetDefaultLevels() + { + Debug.Console(0, this, "SetDefaultLevels not implemented"); + } + + /// + /// + /// + /// + /// + bool DoRoute(SourceRouteListItem route) + { + IRoutingSinkNoSwitching dest = null; + + if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase)) + dest = DefaultAudioDevice; + //else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) + // dest = DefaultDisplay; + else + dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching; + + if (dest == null) + { + Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey); + return false; + } + + if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) + { + dest.ReleaseRoute(); + if (dest is IPower) + (dest as IPower).PowerOff(); + } + else + { + var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs; + if (source == null) + { + Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey); + return false; + } + dest.ReleaseAndMakeRoute(source, route.Type); + } + return true; } public override void RoomVacatedForTimeoutPeriod(object o) { //Implement this - } - - } + } + + } } \ No newline at end of file diff --git a/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs index 1fc7b33b..a20bd3e8 100644 --- a/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs +++ b/Essentials/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs @@ -1,693 +1,698 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; - -namespace PepperDash.Essentials -{ - /// - /// Where all UI element common joins are defined - /// - public class UIBoolJoin - { - /// - /// 901 - /// - public const uint VolumeUpPress = 901; - /// - /// 902 - /// - public const uint VolumeDownPress = 902; - - //**************************************************** - // Codec General - - /// - /// 1001 - /// - public const uint CallEndPress = 1001; - /// - /// 1002 - /// - public const uint CallEndAllConfirmPress = 1002; - /// - /// 1003 - For tapping the text field to reveal the keyboard - /// - public const uint CodecDirectorySearchTextPress = 1003; - - - // Audio Conference - /// - /// 1101 - /// - public const uint ACKeypadVisible = 1101; - /// - /// 1102 - /// - public const uint ACStagingPopoverVisible = 1102; - /// - /// 1111 - /// - public const uint ACSpeedDial1Press = 1111; - /// - /// 1112 - /// - public const uint ACSpeedDial2Press = 1112; - /// - /// 1113 - /// - public const uint ACSpeedDial3Press = 1113; - /// - /// 1114 - /// - public const uint ACSpeedDial4Press = 1114; - /// - /// 1121 - /// - public const uint ACSpeedDial1Visible = 1121; - /// - /// 1122 - /// - public const uint ACSpeedDial2Visible = 1122; - /// - /// 1123 - /// - public const uint ACSpeedDial3Visible = 1123; - /// - /// 1124 - /// - public const uint ACSpeedDial4Visible = 1124; - - //****************************************************** - // Video Conference - /// - /// 1201 - /// - public const uint VCKeypadWithFavoritesVisible = 1201; - /// - /// 1202 - /// - public const uint VCStagingInactivePopoverVisible = 1202; - /// - /// - /// - public const uint VCStagingActivePopoverVisible = 1203; - /// - /// - /// - public const uint VCKeypadVisible = 1204; - /// - /// 1205 - /// - public const uint VCDirectoryVisible = 1205; - /// - /// 1206 - /// - public const uint VCRecentsVisible = 1206; - /// - /// 1207 - /// - public const uint VCCameraVisible = 1207; - /// - /// 1208 - /// - public const uint VCSelfViewLayoutVisible = 1208; - /// - /// 1211 - /// - public const uint VCFavorite1Press = 1211; - /// - /// 1212 - /// - public const uint VCFavorite2Press = 1212; - /// - /// 1213 - /// - public const uint VCFavorite3Press = 1213; - /// - /// 1214 - /// - public const uint VCFavorite4Press = 1214; - /// - /// 1221 - /// - public const uint VCFavorite1Visible = 1221; - /// - /// 1222 - /// - public const uint VCFavorite2Visible = 1222; - /// - /// 1223 - /// - public const uint VCFavorite3Visible = 1223; - /// - /// 1224 - /// - public const uint VCFavorite4Visible = 1224; - /// - /// 1231 - /// - public const uint VCStagingRecentsPress = 1231; - /// - /// 1232 - /// - public const uint VCStagingDirectoryPress = 1232; - /// - /// 1233 - /// - public const uint VCStagingKeypadPress = 1233; - /// - /// 1234 - /// - public const uint VCStagingConnectPress = 1234; - /// - /// 1235 - /// - public const uint VCStagingCameraPress = 1235; - /// - /// 1236 - /// - public const uint VCStagingConnectEnable = 1236; - /// - /// 1237 - When the user touches the text field, should trigger keyboard - /// - public const uint VCKeypadTextPress = 1237; - /// - /// 1238 - /// - public const uint VCKeypadBackspacePress = 1238; - /// - /// 1239 - /// - public const uint VCKeypadBackspaceVisible = 1239; - /// - /// 1240 - /// - public const uint VCDirectoryBackPress = 1240; - /// - /// 1241 For touching the text area to bring up keyboard - /// - public const uint VcDirectoryTextEntryPress = 1241; - /// - /// 1242 - /// - public const uint VCStagingSelfViewLayoutPress = 1242; - - /// - /// 1251 - /// - public const uint VCSelfViewTogglePress = 1251; - /// - /// 1252 - /// - public const uint VCRemoteViewTogglePress = 1252; - /// - /// 1253 - /// - public const uint VCSelfViewPipTogglePress = 1253; - - //****************************************************** - // Keyboard - /// - /// 2901 - /// - public const uint KeyboardVisible = 2901; - /// - /// 2902 - /// - public const uint KeyboardClosePress = 2902; - /// - /// 2903 - /// - public const uint KeyboardButton1Press = 2903; - /// - /// 2904 - /// - public const uint KeyboardButton2Press = 2904; - - // Letter joins start at 2921; - - /// - /// 3101 - /// - public const uint TechExitButton = 3101; - /// - /// 3106 - /// - public const uint TechCommonItemsVisbible = 3106; - /// - /// 3107 - /// - public const uint TechSystemStatusVisible = 3107; - /// - /// 3108 - /// - public const uint TechDisplayControlsVisible = 3108; - /// - /// 3109 - /// - public const uint TechPanelSetupVisible = 3109; - /// - /// 3110 - /// - public const uint TechAdvancedVolumeVisible = 3110; - /// - /// 3111 - /// - public const uint TechAboutVisible = 3111; - /// - /// 3112 - /// - public const uint TechSchedulerVisible = 3112; - - //****************************************************** - /// - /// 3811 - /// - public const uint VolumeSingleMute1Visible = 3811; - /// - /// 3812 - /// - public const uint VolumeSlider1Press = 3812; - /// - /// 3813 - /// - public const uint Volume1ProgramMutePressAndFB = 3813; - /// - /// 3821 - /// - public const uint Volume2Visible = 3821; - /// - /// 3822 - /// - public const uint VolumeSlider2Press = 3822; - /// - /// 3823 - /// - public const uint Volume2MutePressAndFB = 3823; - /// - /// 3831 - /// - public const uint Volume3Visible = 3831; - /// - /// 3832 - /// - public const uint VolumeSlider3Press = 3832; - /// - /// 3833 - /// - public const uint Volume3MutePressAndFB = 3833; - /// - /// 3841 - /// - public const uint Volume4Visible = 3841; - /// - /// 3842 - /// - public const uint VolumeSlider4Press = 3842; - /// - /// 3843 - /// - public const uint Volume4MutePressAndFB = 3843; - /// - /// 3851 - /// - public const uint Volume5Visible = 3851; - /// - /// 3852 - /// - public const uint VolumeSlider5Press = 3852; - /// - /// 3853 - /// - public const uint Volume5MutePressAndFB = 3853; - /// - /// 3861 - /// - public const uint Volume6Visible = 3861; - /// - /// 3862 - /// - public const uint VolumeSlider6Press = 3862; - /// - /// 3863 - /// - public const uint Volume6MutePressAndFB = 3863; - - /// - /// 3869 - when the system is off and the gear is pressed - /// - public const uint VolumesPagePowerOffVisible = 3869; - /// - /// 3870 - /// - public const uint VolumesPageVisible = 3870; - /// - /// 3871 - /// - public const uint VolumeDualMute1Visible = 3871; - /// - /// 3874 - /// - public const uint Volume1SpeechMutePressAndFB = 3874; - /// - /// 3875 - /// - public const uint Volume1BackerVisibility = 3875; - /// - /// 3891 - /// - public const uint VolumeDefaultPress = 3891; - - - /// - /// 3999 - /// - public const uint GenericModalVisible = 3999; - /// - /// 12345 - /// - public const uint AvNoControlsSubVisible = 12345; - - // 10000 - 14999 are general "source" pages - - /// - /// 15001 - /// - public const uint StartPageVisible = 15001; - /// - /// 15002 Shows the start page in the source controls area of the screen - /// - public const uint TapToBeginVisible = 15002; - /// - /// 15003 Message text when no source is showing - /// - public const uint SelectASourceVisible = 15003; - /// - /// 15004 - /// - public const uint RoomIsOn = 15004; - /// - /// 15005 Shows always-on volume control subpage with only audio mute - /// - public const uint VolumeControlsSingleMuteVisible = 15005; - /// - /// 15006 Shows always-on volume control subpage with mic and audio mutes - /// - public const uint VolumeControlsDualMuteVisible = 15006; - /// - /// 15010 - /// - public const uint ShowPanelSetupPress = 15010; - /// - /// 15011 - Top bar with room name and button that pops up dialog with room data - /// - public const uint TopBarHabaneroVisible = 15011; - /// - /// 15012 - /// - public const uint SourceStagingBarVisible = 15012; - /// - /// 15013 - /// - public const uint PowerOffStep1Visible = 15013; - /// - /// 15014 - /// - public const uint PowerOffStep2Visible = 15014; - /// - /// 15015 - /// - public const uint ShowPowerOffPress = 15015; - /// - /// 15016 - /// - public const uint PowerOffMorePress = 15016; - /// - /// 15017 - /// - public const uint StagingPageAdditionalArrowsVisible = 15017; - /// - /// 15018 The Header with dynamic buttons - /// - public const uint TopBarHabaneroDynamicVisible = 15018; - /// - /// 15020 - /// - public const uint PanelSetupVisible = 15020; - /// - /// 15021 - /// - public const uint SourceWaitOverlayVisible = 15021; - /// - /// 15022 - /// - public const uint ActivityFooterVisible = 15022; - /// - /// 15023 - /// - public const uint HeaderLightsButtonVisible = 15023; - /// - /// 15024 - /// - public const uint HeaderCallRightButtonVisible = 15024; - /// - /// 15025 - /// - public const uint HeaderCallLeftButtonVisible = 15025; - /// - /// 15026 - /// - public const uint HeaderLightsButtonPress = 15026; - /// [- - /// 15027 - /// - public const uint HeaderCallButtonPress = 15027; - /// - /// 15028 The gear button in header - /// - public const uint HeaderGearButtonPress = 15028; - /// - /// 15029 the room button in header - /// - public const uint HeaderRoomButtonPress = 15029; - /// - /// 15030 Visibility for room data popup - /// - public const uint RoomHeaderPageVisible = 15030; - /// - /// 15031 - /// - public const uint AllRoomsOffPress = 15031; - /// - /// 15032 - /// - public const uint DisplayPowerTogglePress = 15032; - /// - /// 15033 - /// - public const uint PowerOffCancelPress = 15033; - /// - /// 15034 - /// - public const uint PowerOffConfirmPress = 15034; - /// - /// 15035 - /// - public const uint VolumeButtonPopupPress = 15035; - /// - /// 15035 - /// - public const uint VolumeButtonPopupVisible = 15035; - /// - /// 15036 - /// - public const uint VolumeGaugePopupVisible = 15036; - /// - /// 15037 - /// - public const uint GearButtonVisible = 15037; - /// - /// 15038 - /// - public const uint CalendarHeaderButtonVisible = 15038; - /// - /// 15039 - /// - public const uint CalendarHeaderButtonPress = 15039; - /// - /// 15040 - /// - public const uint CallStatusPageVisible = 15040; - /// - /// 15041 - /// - public const uint LightsPageVisible = 15041; - /// - /// 15042 Closes whichever interlocked modal is open - /// - public const uint InterlockedModalClosePress = 15042; - /// - /// 15043 Vis for modal backer for full-screen source - /// - public const uint SourceBackgroundOverlayVisible = 15043; - /// - /// 15044 Close button for source modal overlay - /// - public const uint SourceBackgroundOverlayClosePress = 15044; - /// - /// 15045 - Visibility for the bar containing call navigation button list - /// - public const uint CallStagingBarVisible = 15045; - /// - /// 15046 - /// - public const uint MeetingsListVisible = 15046; - /// - /// 15047 The "Join" button on the next meeting ribbon - /// - public const uint NextMeetingRibbonJoinPress = 15047; - /// - /// 15048 Dismisses the ribbon - /// - public const uint NextMeetingRibbonClosePress = 15048; - /// - /// 15049 - /// - public const uint NextMeetingRibbonVisible = 15049; - /// - /// 15051 - /// - public const uint Display1SelectPressAndFb = 15051; - /// - /// 15052 - /// - public const uint Display1ControlButtonEnable = 15052; - /// - /// 15053 - /// - public const uint Display1ControlButtonPress = 15053; - /// - /// 15054 - /// - public const uint Display1AudioButtonEnable = 15054; - /// - /// 15055 - /// - public const uint Display1AudioButtonPressAndFb = 15055; - /// - /// 15056 - /// - public const uint Display2SelectPressAndFb = 15056; - /// - /// 15057 - /// - public const uint Display2ControlButtonEnable = 15057; - /// - /// 15058 - /// - public const uint Display2ControlButtonPress = 15058; - /// - /// 15059 - /// - public const uint Display2AudioButtonEnable = 15059; - /// - /// 15060 - /// - public const uint Display2AudioButtonPressAndFb = 15060; - /// - /// 15061 Reveals the dual-display subpage - /// - public const uint DualDisplayPageVisible = 15061; - /// - /// 15062 Reveals the toggle switch for the sharing mode - /// - public const uint ToggleSharingModeVisible = 15062; - /// - /// 15063 Press for the toggle mode switch - /// - public const uint ToggleSharingModePress = 15063; - /// - /// 15064 - /// - public const uint LogoDefaultVisible = 15064; - /// - /// 15065 - /// - public const uint LogoUrlVisible = 15065; - /// - /// 15066 - Reveals the active calls header item - /// - public const uint HeaderActiveCallsListVisible = 15066; - /// - /// 15067 - /// - public const uint NotificationRibbonVisible = 15067; - /// - /// 15083 - Press for Call help desk on AC/VC - /// - public const uint HelpPageShowCallButtonPress = 15083; - /// - /// 15084 - Show the "call help desk" button on help page - /// - public const uint HelpPageShowCallButtonVisible = 15084; - /// - /// 15085 Visibility join for help subpage - /// - public const uint HelpPageVisible = 15085; - /// - /// 15086 Press for help header button - /// - public const uint HelpPress = 15086; - /// - /// 15088 - /// - public const uint DateOnlyVisible = 15088; - /// - /// 15089 - /// - public const uint TimeOnlyVisible = 15089; - /// - /// 15090 - /// - public const uint DateAndTimeVisible = 15090; - /// - /// 15091 - /// - public const uint SetupFullDistrib = 15091; - - // PIN dialogs ************************************ - - /// - /// 15201 - /// - public const uint PinDialog4DigitVisible = 15201; - /// - /// 15206 - /// - public const uint PinDialogCancelPress = 15206; - /// - /// 15207 - /// - public const uint PinDialogErrorVisible = 15207; - /// - /// 15211 - /// - public const uint PinDialogDot1 = 15211; - /// - /// 15212 - /// - public const uint PinDialogDot2 = 15212; - /// - /// 15213 - /// - public const uint PinDialogDot3 = 15213; - /// - /// 15214 - /// - public const uint PinDialogDot4 = 15214; - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; + +namespace PepperDash.Essentials +{ + /// + /// Where all UI element common joins are defined + /// + public class UIBoolJoin + { + /// + /// 901 + /// + public const uint VolumeUpPress = 901; + /// + /// 902 + /// + public const uint VolumeDownPress = 902; + + //**************************************************** + // Codec General + + /// + /// 1001 + /// + public const uint CallEndPress = 1001; + /// + /// 1002 + /// + public const uint CallEndAllConfirmPress = 1002; + /// + /// 1003 - For tapping the text field to reveal the keyboard + /// + public const uint CodecDirectorySearchTextPress = 1003; + + + // Audio Conference + /// + /// 1101 + /// + public const uint ACKeypadVisible = 1101; + /// + /// 1102 + /// + public const uint ACStagingPopoverVisible = 1102; + /// + /// 1111 + /// + public const uint ACSpeedDial1Press = 1111; + /// + /// 1112 + /// + public const uint ACSpeedDial2Press = 1112; + /// + /// 1113 + /// + public const uint ACSpeedDial3Press = 1113; + /// + /// 1114 + /// + public const uint ACSpeedDial4Press = 1114; + /// + /// 1121 + /// + public const uint ACSpeedDial1Visible = 1121; + /// + /// 1122 + /// + public const uint ACSpeedDial2Visible = 1122; + /// + /// 1123 + /// + public const uint ACSpeedDial3Visible = 1123; + /// + /// 1124 + /// + public const uint ACSpeedDial4Visible = 1124; + + //****************************************************** + // Video Conference + /// + /// 1201 + /// + public const uint VCKeypadWithFavoritesVisible = 1201; + /// + /// 1202 + /// + public const uint VCStagingInactivePopoverVisible = 1202; + /// + /// + /// + public const uint VCStagingActivePopoverVisible = 1203; + /// + /// + /// + public const uint VCKeypadVisible = 1204; + /// + /// 1205 + /// + public const uint VCDirectoryVisible = 1205; + /// + /// 1206 + /// + public const uint VCRecentsVisible = 1206; + /// + /// 1207 + /// + public const uint VCCameraVisible = 1207; + /// + /// 1208 + /// + public const uint VCSelfViewLayoutVisible = 1208; + /// + /// 1211 + /// + public const uint VCFavorite1Press = 1211; + /// + /// 1212 + /// + public const uint VCFavorite2Press = 1212; + /// + /// 1213 + /// + public const uint VCFavorite3Press = 1213; + /// + /// 1214 + /// + public const uint VCFavorite4Press = 1214; + /// + /// 1221 + /// + public const uint VCFavorite1Visible = 1221; + /// + /// 1222 + /// + public const uint VCFavorite2Visible = 1222; + /// + /// 1223 + /// + public const uint VCFavorite3Visible = 1223; + /// + /// 1224 + /// + public const uint VCFavorite4Visible = 1224; + /// + /// 1231 + /// + public const uint VCStagingRecentsPress = 1231; + /// + /// 1232 + /// + public const uint VCStagingDirectoryPress = 1232; + /// + /// 1233 + /// + public const uint VCStagingKeypadPress = 1233; + /// + /// 1234 + /// + public const uint VCStagingConnectPress = 1234; + /// + /// 1235 + /// + public const uint VCStagingCameraPress = 1235; + /// + /// 1236 + /// + public const uint VCStagingConnectEnable = 1236; + /// + /// 1237 - When the user touches the text field, should trigger keyboard + /// + public const uint VCKeypadTextPress = 1237; + /// + /// 1238 + /// + public const uint VCKeypadBackspacePress = 1238; + /// + /// 1239 + /// + public const uint VCKeypadBackspaceVisible = 1239; + /// + /// 1240 + /// + public const uint VCDirectoryBackPress = 1240; + /// + /// 1241 For touching the text area to bring up keyboard + /// + public const uint VCDirectoryTextEntryPress = 1241; + /// + /// 1242 + /// + public const uint VCStagingSelfViewLayoutPress = 1242; + + /// + /// 1243 + /// + public const uint VCDirectoryBackVisible = 1243; + + /// + /// 1251 + /// + public const uint VCSelfViewTogglePress = 1251; + /// + /// 1252 + /// + public const uint VCRemoteViewTogglePress = 1252; + /// + /// 1253 + /// + public const uint VCSelfViewPipTogglePress = 1253; + + //****************************************************** + // Keyboard + /// + /// 2901 + /// + public const uint KeyboardVisible = 2901; + /// + /// 2902 + /// + public const uint KeyboardClosePress = 2902; + /// + /// 2903 + /// + public const uint KeyboardButton1Press = 2903; + /// + /// 2904 + /// + public const uint KeyboardButton2Press = 2904; + + // Letter joins start at 2921; + + /// + /// 3101 + /// + public const uint TechExitButton = 3101; + /// + /// 3106 + /// + public const uint TechCommonItemsVisbible = 3106; + /// + /// 3107 + /// + public const uint TechSystemStatusVisible = 3107; + /// + /// 3108 + /// + public const uint TechDisplayControlsVisible = 3108; + /// + /// 3109 + /// + public const uint TechPanelSetupVisible = 3109; + /// + /// 3110 + /// + public const uint TechAdvancedVolumeVisible = 3110; + /// + /// 3111 + /// + public const uint TechAboutVisible = 3111; + /// + /// 3112 + /// + public const uint TechSchedulerVisible = 3112; + + //****************************************************** + /// + /// 3811 + /// + public const uint VolumeSingleMute1Visible = 3811; + /// + /// 3812 + /// + public const uint VolumeSlider1Press = 3812; + /// + /// 3813 + /// + public const uint Volume1ProgramMutePressAndFB = 3813; + /// + /// 3821 + /// + public const uint Volume2Visible = 3821; + /// + /// 3822 + /// + public const uint VolumeSlider2Press = 3822; + /// + /// 3823 + /// + public const uint Volume2MutePressAndFB = 3823; + /// + /// 3831 + /// + public const uint Volume3Visible = 3831; + /// + /// 3832 + /// + public const uint VolumeSlider3Press = 3832; + /// + /// 3833 + /// + public const uint Volume3MutePressAndFB = 3833; + /// + /// 3841 + /// + public const uint Volume4Visible = 3841; + /// + /// 3842 + /// + public const uint VolumeSlider4Press = 3842; + /// + /// 3843 + /// + public const uint Volume4MutePressAndFB = 3843; + /// + /// 3851 + /// + public const uint Volume5Visible = 3851; + /// + /// 3852 + /// + public const uint VolumeSlider5Press = 3852; + /// + /// 3853 + /// + public const uint Volume5MutePressAndFB = 3853; + /// + /// 3861 + /// + public const uint Volume6Visible = 3861; + /// + /// 3862 + /// + public const uint VolumeSlider6Press = 3862; + /// + /// 3863 + /// + public const uint Volume6MutePressAndFB = 3863; + + /// + /// 3869 - when the system is off and the gear is pressed + /// + public const uint VolumesPagePowerOffVisible = 3869; + /// + /// 3870 + /// + public const uint VolumesPageVisible = 3870; + /// + /// 3871 + /// + public const uint VolumeDualMute1Visible = 3871; + /// + /// 3874 + /// + public const uint Volume1SpeechMutePressAndFB = 3874; + /// + /// 3875 + /// + public const uint Volume1BackerVisibility = 3875; + /// + /// 3891 + /// + public const uint VolumeDefaultPress = 3891; + + + /// + /// 3999 + /// + public const uint GenericModalVisible = 3999; + /// + /// 12345 + /// + public const uint AvNoControlsSubVisible = 12345; + + // 10000 - 14999 are general "source" pages + + /// + /// 15001 + /// + public const uint StartPageVisible = 15001; + /// + /// 15002 Shows the start page in the source controls area of the screen + /// + public const uint TapToBeginVisible = 15002; + /// + /// 15003 Message text when no source is showing + /// + public const uint SelectASourceVisible = 15003; + /// + /// 15004 + /// + public const uint RoomIsOn = 15004; + /// + /// 15005 Shows always-on volume control subpage with only audio mute + /// + public const uint VolumeControlsSingleMuteVisible = 15005; + /// + /// 15006 Shows always-on volume control subpage with mic and audio mutes + /// + public const uint VolumeControlsDualMuteVisible = 15006; + /// + /// 15010 + /// + public const uint ShowPanelSetupPress = 15010; + /// + /// 15011 - Top bar with room name and button that pops up dialog with room data + /// + public const uint TopBarHabaneroVisible = 15011; + /// + /// 15012 + /// + public const uint SourceStagingBarVisible = 15012; + /// + /// 15013 + /// + public const uint PowerOffStep1Visible = 15013; + /// + /// 15014 + /// + public const uint PowerOffStep2Visible = 15014; + /// + /// 15015 + /// + public const uint ShowPowerOffPress = 15015; + /// + /// 15016 + /// + public const uint PowerOffMorePress = 15016; + /// + /// 15017 + /// + public const uint StagingPageAdditionalArrowsVisible = 15017; + /// + /// 15018 The Header with dynamic buttons + /// + public const uint TopBarHabaneroDynamicVisible = 15018; + /// + /// 15020 + /// + public const uint PanelSetupVisible = 15020; + /// + /// 15021 + /// + public const uint SourceWaitOverlayVisible = 15021; + /// + /// 15022 + /// + public const uint ActivityFooterVisible = 15022; + /// + /// 15023 + /// + public const uint HeaderLightsButtonVisible = 15023; + /// + /// 15024 + /// + public const uint HeaderCallRightButtonVisible = 15024; + /// + /// 15025 + /// + public const uint HeaderCallLeftButtonVisible = 15025; + /// + /// 15026 + /// + public const uint HeaderLightsButtonPress = 15026; + /// [- + /// 15027 + /// + public const uint HeaderCallButtonPress = 15027; + /// + /// 15028 The gear button in header + /// + public const uint HeaderGearButtonPress = 15028; + /// + /// 15029 the room button in header + /// + public const uint HeaderRoomButtonPress = 15029; + /// + /// 15030 Visibility for room data popup + /// + public const uint RoomHeaderPageVisible = 15030; + /// + /// 15031 + /// + public const uint AllRoomsOffPress = 15031; + /// + /// 15032 + /// + public const uint DisplayPowerTogglePress = 15032; + /// + /// 15033 + /// + public const uint PowerOffCancelPress = 15033; + /// + /// 15034 + /// + public const uint PowerOffConfirmPress = 15034; + /// + /// 15035 + /// + public const uint VolumeButtonPopupPress = 15035; + /// + /// 15035 + /// + public const uint VolumeButtonPopupVisible = 15035; + /// + /// 15036 + /// + public const uint VolumeGaugePopupVisible = 15036; + /// + /// 15037 + /// + public const uint GearButtonVisible = 15037; + /// + /// 15038 + /// + public const uint CalendarHeaderButtonVisible = 15038; + /// + /// 15039 + /// + public const uint CalendarHeaderButtonPress = 15039; + /// + /// 15040 + /// + public const uint CallStatusPageVisible = 15040; + /// + /// 15041 + /// + public const uint LightsPageVisible = 15041; + /// + /// 15042 Closes whichever interlocked modal is open + /// + public const uint InterlockedModalClosePress = 15042; + /// + /// 15043 Vis for modal backer for full-screen source + /// + public const uint SourceBackgroundOverlayVisible = 15043; + /// + /// 15044 Close button for source modal overlay + /// + public const uint SourceBackgroundOverlayClosePress = 15044; + /// + /// 15045 - Visibility for the bar containing call navigation button list + /// + public const uint CallStagingBarVisible = 15045; + /// + /// 15046 + /// + public const uint MeetingsListVisible = 15046; + /// + /// 15047 The "Join" button on the next meeting ribbon + /// + public const uint NextMeetingRibbonJoinPress = 15047; + /// + /// 15048 Dismisses the ribbon + /// + public const uint NextMeetingRibbonClosePress = 15048; + /// + /// 15049 + /// + public const uint NextMeetingRibbonVisible = 15049; + /// + /// 15051 + /// + public const uint Display1SelectPressAndFb = 15051; + /// + /// 15052 + /// + public const uint Display1ControlButtonEnable = 15052; + /// + /// 15053 + /// + public const uint Display1ControlButtonPress = 15053; + /// + /// 15054 + /// + public const uint Display1AudioButtonEnable = 15054; + /// + /// 15055 + /// + public const uint Display1AudioButtonPressAndFb = 15055; + /// + /// 15056 + /// + public const uint Display2SelectPressAndFb = 15056; + /// + /// 15057 + /// + public const uint Display2ControlButtonEnable = 15057; + /// + /// 15058 + /// + public const uint Display2ControlButtonPress = 15058; + /// + /// 15059 + /// + public const uint Display2AudioButtonEnable = 15059; + /// + /// 15060 + /// + public const uint Display2AudioButtonPressAndFb = 15060; + /// + /// 15061 Reveals the dual-display subpage + /// + public const uint DualDisplayPageVisible = 15061; + /// + /// 15062 Reveals the toggle switch for the sharing mode + /// + public const uint ToggleSharingModeVisible = 15062; + /// + /// 15063 Press for the toggle mode switch + /// + public const uint ToggleSharingModePress = 15063; + /// + /// 15064 + /// + public const uint LogoDefaultVisible = 15064; + /// + /// 15065 + /// + public const uint LogoUrlVisible = 15065; + /// + /// 15066 - Reveals the active calls header item + /// + public const uint HeaderActiveCallsListVisible = 15066; + /// + /// 15067 + /// + public const uint NotificationRibbonVisible = 15067; + /// + /// 15083 - Press for Call help desk on AC/VC + /// + public const uint HelpPageShowCallButtonPress = 15083; + /// + /// 15084 - Show the "call help desk" button on help page + /// + public const uint HelpPageShowCallButtonVisible = 15084; + /// + /// 15085 Visibility join for help subpage + /// + public const uint HelpPageVisible = 15085; + /// + /// 15086 Press for help header button + /// + public const uint HelpPress = 15086; + /// + /// 15088 + /// + public const uint DateOnlyVisible = 15088; + /// + /// 15089 + /// + public const uint TimeOnlyVisible = 15089; + /// + /// 15090 + /// + public const uint DateAndTimeVisible = 15090; + /// + /// 15091 + /// + public const uint SetupFullDistrib = 15091; + + // PIN dialogs ************************************ + + /// + /// 15201 + /// + public const uint PinDialog4DigitVisible = 15201; + /// + /// 15206 + /// + public const uint PinDialogCancelPress = 15206; + /// + /// 15207 + /// + public const uint PinDialogErrorVisible = 15207; + /// + /// 15211 + /// + public const uint PinDialogDot1 = 15211; + /// + /// 15212 + /// + public const uint PinDialogDot2 = 15212; + /// + /// 15213 + /// + public const uint PinDialogDot3 = 15213; + /// + /// 15214 + /// + public const uint PinDialogDot4 = 15214; + } } \ No newline at end of file diff --git a/Essentials/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs b/Essentials/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs index f3d21d2c..af461fb9 100644 --- a/Essentials/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs +++ b/Essentials/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs @@ -29,9 +29,9 @@ namespace PepperDash.Essentials /// /// 1231 - 1261 range of joins for recent list time /// - public const uint VCRecentListTimeTextStart = 1231; - // - public const uint VCRecentListTimeTextEnd = 1260; + public const uint VCRecentListTimeTextStart = 1231; + // RANGE IN USE + public const uint VCRecentListTimeTextEnd = 1260; /// /// 1291 - the current layout mode /// @@ -42,7 +42,33 @@ namespace PepperDash.Essentials /// public const uint VCDirectoryListTextStart = 1301; // RANGE IN USE - public const uint VCDirectoryListTextEnd = 1400; + public const uint VCDirectoryListTextEnd = 1400; + + /// + /// 141112 + /// + public const uint VCFavorites1Text = 1411; + + /// + /// 1412 + /// + public const uint VCFavorites2Text = 1412; + + /// + /// 1413 + /// + public const uint VCFavorites3Text = 1413; + + /// + /// 1414 + /// + public const uint VCFavorites4Text = 1414; + + /// + /// 1415 + /// + public const uint VCFavorites5Text = 1415; + //****************************************************** // Keyboard diff --git a/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 17468457..8c95fa94 100644 --- a/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/Essentials/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -10,6 +10,7 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; using PepperDash.Essentials.Core.PageManagers; using PepperDash.Essentials.Room.Config; +using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials @@ -408,7 +409,7 @@ namespace PepperDash.Essentials TriList.SetSigFalseAction(UIBoolJoin.NextMeetingRibbonJoinPress, () => { HideNextMeetingPopup(); - RoomOnAndDialMeeting(meeting.ConferenceNumberToDial); + RoomOnAndDialMeeting(meeting); }); TriList.SetString(UIStringJoin.NextMeetingSecondaryButtonLabel, "Show Schedule"); TriList.SetSigFalseAction(UIBoolJoin.CalendarHeaderButtonPress, () => @@ -459,13 +460,15 @@ namespace PepperDash.Essentials /// /// Dials a meeting after turning on room (if necessary) /// - void RoomOnAndDialMeeting(string number) + void RoomOnAndDialMeeting(Meeting meeting) { Action dialAction = () => { var d = CurrentRoom.ScheduleSource as VideoCodecBase; - if (d != null) - d.Dial(number); + if (d != null) + { + d.Dial(meeting); + } }; if (CurrentRoom.OnFeedback.BoolValue) dialAction(); @@ -980,7 +983,7 @@ namespace PepperDash.Essentials PopupInterlock.Hide(); var d = CurrentRoom.ScheduleSource as VideoCodecBase; if (d != null) - RoomOnAndDialMeeting(mm.ConferenceNumberToDial); + RoomOnAndDialMeeting(mm); }); } MeetingsSrl.Count = i; diff --git a/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 39a8624c..7f261001 100644 --- a/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/Essentials/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -61,6 +61,10 @@ namespace PepperDash.Essentials.UIDrivers.VC CodecDirectory CurrentDirectoryResult; + string LastFolderRequestedParentFolderId; + + BoolFeedback DirectoryBackButtonVisibleFeedback; + // These are likely temp until we get a keyboard built StringFeedback DialStringFeedback; StringBuilder DialStringBuilder = new StringBuilder(); @@ -130,6 +134,12 @@ namespace PepperDash.Essentials.UIDrivers.VC DialStringBackspaceVisibleFeedback .LinkInputSig(TriList.BooleanInput[UIBoolJoin.VCKeypadBackspaceVisible]); + TriList.SetSigFalseAction(UIBoolJoin.VCDirectoryBackPress, GetDirectoryParentFolderContents); + + DirectoryBackButtonVisibleFeedback = new BoolFeedback(() => CurrentDirectoryResult != (codec as IHasDirectory).DirectoryRoot); + DirectoryBackButtonVisibleFeedback + .LinkInputSig(TriList.BooleanInput[UIBoolJoin.VCDirectoryBackVisible]); + TriList.SetSigFalseAction(UIBoolJoin.VCKeypadTextPress, RevealKeyboard); // Address and number @@ -389,9 +399,9 @@ namespace PepperDash.Essentials.UIDrivers.VC TriList.SetString(timeTextOffset + i, timeText); string iconName = null; - if (c.Direction == eCodecCallDirection.Incoming) + if (c.OccurenceType == eCodecOccurrenceType.Received) iconName = "Left"; - else if (c.Direction == eCodecCallDirection.Outgoing) + else if (c.OccurenceType == eCodecOccurrenceType.Placed) iconName = "Right"; else iconName = "Help"; @@ -419,7 +429,7 @@ namespace PepperDash.Essentials.UIDrivers.VC if (i < favs.Count) { var fav = favs[(int)i]; - TriList.SetString(1211 + i, fav.Name); + TriList.SetString(1411 + i, fav.Name); TriList.SetBool(1221 + i, true); TriList.SetSigFalseAction(1211 + i, () => { @@ -445,7 +455,14 @@ namespace PepperDash.Essentials.UIDrivers.VC DirectoryList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCDirectoryList], true, 1300); codec.DirectoryResultReturned += new EventHandler(dir_DirectoryResultReturned); - CurrentDirectoryResult = codec.DirectoryRoot; + + if (codec.PhonebookSyncState.InitialSyncComplete) + SetCurrentDirectoryToRoot(); + else + { + codec.PhonebookSyncState.InitialSyncCompleted += new EventHandler(PhonebookSyncState_InitialSyncCompleted); + } + // If there is something here now, show it otherwise wait for the event if (CurrentDirectoryResult != null && codec.DirectoryRoot.DirectoryResults.Count > 0) @@ -456,6 +473,37 @@ namespace PepperDash.Essentials.UIDrivers.VC } } + /// + /// Sets the current directory resutls to the DirectorRoot and updates Back Button visibiltiy + /// + void SetCurrentDirectoryToRoot() + { + LastFolderRequestedParentFolderId = string.Empty; + + CurrentDirectoryResult = (Codec as IHasDirectory).DirectoryRoot; + + DirectoryBackButtonVisibleFeedback.FireUpdate(); + + RefreshDirectory(); + } + + /// + /// Setup the Directory list when notified that the initial phonebook sync is completed + /// + /// + /// + void PhonebookSyncState_InitialSyncCompleted(object sender, EventArgs e) + { + var codec = Codec as IHasDirectory; + + SetCurrentDirectoryToRoot(); + + if (CurrentDirectoryResult != null && codec.DirectoryRoot.DirectoryResults.Count > 0) + { + RefreshDirectory(); + } + } + /// /// /// @@ -464,9 +512,38 @@ namespace PepperDash.Essentials.UIDrivers.VC void dir_DirectoryResultReturned(object sender, DirectoryEventArgs e) { CurrentDirectoryResult = e.Directory; + DirectoryBackButtonVisibleFeedback.FireUpdate(); RefreshDirectory(); } + /// + /// Helper method to retrieve directory folder contents and store last requested folder id + /// + /// + void GetDirectoryFolderContents(DirectoryFolder folder) + { + LastFolderRequestedParentFolderId = folder.ParentFolderId; + + (Codec as IHasDirectory).GetDirectoryFolderContents(folder.FolderId); + } + + /// + /// Request the parent folder contents or sets back to the root if no parent folder + /// + void GetDirectoryParentFolderContents() + { + var codec = Codec as IHasDirectory; + + if (!string.IsNullOrEmpty(LastFolderRequestedParentFolderId)) + codec.GetDirectoryFolderContents(LastFolderRequestedParentFolderId); + else + { + SetCurrentDirectoryToRoot(); + } + + + } + /// /// /// @@ -484,9 +561,11 @@ namespace PepperDash.Essentials.UIDrivers.VC } i++; - DirectoryList.SetItemMainText(i, r.Name); + if(r is DirectoryContact) { + DirectoryList.SetItemMainText(i, r.Name); + var dc = r as DirectoryContact; // if more than one contact method, pop up modal to choose // otherwiese dial 0 entry @@ -499,15 +578,18 @@ namespace PepperDash.Essentials.UIDrivers.VC } } - else + else // is DirectoryFolder { + DirectoryList.SetItemMainText(i, string.Format("[+] {0}", r.Name)); + + var df = r as DirectoryFolder; + DirectoryList.SetItemButtonAction(i, b => { if (!b) { - var id = (r as DirectoryFolder).FolderId; - (Codec as IHasDirectory).GetDirectoryFolderContents(id); - // will later call event handler + GetDirectoryFolderContents(df); + // will later call event handler after folder contents retrieved } }); }