Worked on VC directory and favorites. Fixed various bugs.

This commit is contained in:
Neil Dorin
2017-10-11 21:43:14 -06:00
parent 2def648596
commit fb0a91b454
16 changed files with 1895 additions and 1674 deletions

View File

@@ -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)
});
}

View File

@@ -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<DirectoryItem> DirectoryResults { get; private set; }
//public int Offset { get; private set; }
public string ResultsFolderId { get; set; }
//public int Limit { get; private set; }

View File

@@ -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<Call> Calls { get; private set; }
public Meeting()
{
Calls = new List<Call>();
}
}
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

View File

@@ -136,8 +136,8 @@
<Compile Include="Streaming\Roku.cs" />
<Compile Include="VideoCodec\CiscoCodec\BookingsDataClasses.cs" />
<Compile Include="VideoCodec\CiscoCodec\CallHistoryDataClasses.cs" />
<Compile Include="VideoCodec\CiscoCodec\CiscoCodec.cs" />
<Compile Include="VideoCodec\CiscoCodec\CiscoCodecPropertiesConfig.cs" />
<Compile Include="VideoCodec\CiscoCodec\CiscoSparkCodec.cs" />
<Compile Include="VideoCodec\CiscoCodec\CiscoSparkCodecPropertiesConfig.cs" />
<Compile Include="VideoCodec\MockVC\MockVcPropertiesConfig.cs" />
<Compile Include="VideoCodec\CiscoCodec\PhonebookDataClasses.cs" />
<Compile Include="VideoCodec\CiscoCodec\xConfiguration.cs" />

View File

@@ -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<Codec.CiscoCodecPropertiesConfig>(properties.ToString());
return new PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoCodec(key, name, comm, props);
var props = JsonConvert.DeserializeObject<Codec.CiscoSparkCodecPropertiesConfig>(properties.ToString());
return new PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoSparkCodec(key, name, comm, props);
}
else if (groupName == "settopbox") //(typeName == "irstbbase")

View File

@@ -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<Call> Calls { get; set; }
public ConnectMode ConnectMode { get; set; }
public DialInfo()
{
Calls = new List<Call>();
}
}
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);
}
}

View File

@@ -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<DirectoryEventArgs> 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
/// <param name="folderId"></param>
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)
/// <summary>
/// Simple dial method
/// </summary>
/// <param name="number"></param>
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)
/// <summary>
/// Dials a specific meeting
/// </summary>
/// <param name="meeting"></param>
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);
}
}
/// <summary>
/// Detailed dial method
/// </summary>
/// <param name="number"></param>
/// <param name="protocol"></param>
/// <param name="callRate"></param>
/// <param name="callType"></param>
/// <param name="meetingId"></param>
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
}
}
/// <summary>
/// Used to track the status of syncronizing the phonebook values when connecting to a codec or refreshing the phonebook info
/// </summary>
public class CodecPhonebookSyncState : IKeyed
{
bool _InitialSyncComplete;
public event EventHandler<EventArgs> 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;
}
}
}

View File

@@ -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; }

View File

@@ -278,6 +278,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// Converts data returned from a cisco codec to the generic Directory format.
/// </summary>
/// <param name="result"></param>
/// <param name="resultFolder"></param>
/// <returns></returns>
public static CodecDirectory ConvertCiscoPhonebookToGeneric(PhonebookSearchResult result)
{

View File

@@ -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; }
/// <summary>
///
/// </summary>
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<bool> IncomingCallFeedbackFunc
{
get { return () => _IncomingCall; }
}
bool _IncomingCall;
protected override Func<bool> MuteFeedbackFunc
{
get { return () => _IsMuted; }
}
bool _IsMuted;
protected override Func<bool> PrivacyModeIsOnFeedbackFunc
{
get { return () => _PrivacyModeIsOn; }
}
bool _PrivacyModeIsOn;
protected override Func<string> SharingSourceFeedbackFunc
{
get { return () => _SharingSource; }
}
string _SharingSource;
protected override Func<int> VolumeLevelFeedbackFunc
{
get { return () => _VolumeLevel; }
}
int _VolumeLevel;
/// <summary>
/// Dials, yo!
/// </summary>
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);
}
/// <summary>
///
/// </summary>
public override void EndCall(CodecActiveCallItem call)
{
Debug.Console(1, this, "EndCall");
ActiveCalls.Remove(call);
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call);
//ActiveCallCountFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
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();
}
/// <summary>
/// For a call from the test methods below
/// </summary>
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
}
/// <summary>
/// For a call from the test methods below
/// </summary>
public override void RejectCall(CodecActiveCallItem call)
{
Debug.Console(1, this, "RejectCall");
ActiveCalls.Remove(call);
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call);
//ActiveCallCountFeedback.FireUpdate();
}
/// <summary>
/// Makes horrible tones go out on the wire!
/// </summary>
/// <param name="s"></param>
public override void SendDtmf(string s)
{
Debug.Console(1, this, "SendDTMF: {0}", s);
}
/// <summary>
///
/// </summary>
public override void StartSharing()
{
}
/// <summary>
///
/// </summary>
public override void StopSharing()
{
}
/// <summary>
/// Called by routing to make it happen
/// </summary>
/// <param name="selector"></param>
public override void ExecuteSwitch(object selector)
{
Debug.Console(1, this, "ExecuteSwitch: {0}", selector);
_SharingSource = selector.ToString();
}
/// <summary>
///
/// </summary>
public override void MuteOff()
{
_IsMuted = false;
MuteFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
public override void MuteOn()
{
_IsMuted = true;
MuteFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
public override void MuteToggle()
{
_IsMuted = !_IsMuted;
MuteFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
/// <param name="level"></param>
public override void SetVolume(ushort level)
{
_VolumeLevel = level;
VolumeLevelFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
/// <param name="pressRelease"></param>
public override void VolumeDown(bool pressRelease)
{
}
/// <summary>
///
/// </summary>
/// <param name="pressRelease"></param>
public override void VolumeUp(bool pressRelease)
{
}
/// <summary>
///
/// </summary>
public override void PrivacyModeOn()
{
Debug.Console(1, this, "PrivacyMuteOn");
if (_PrivacyModeIsOn)
return;
_PrivacyModeIsOn = true;
PrivacyModeIsOnFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
public override void PrivacyModeOff()
{
Debug.Console(1, this, "PrivacyMuteOff");
if (!_PrivacyModeIsOn)
return;
_PrivacyModeIsOn = false;
PrivacyModeIsOnFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
public override void PrivacyModeToggle()
{
_PrivacyModeIsOn = !_PrivacyModeIsOn;
Debug.Console(1, this, "PrivacyMuteToggle: {0}", _PrivacyModeIsOn);
PrivacyModeIsOnFeedback.FireUpdate();
}
//********************************************************
// SIMULATION METHODS
/// <summary>
///
/// </summary>
/// <param name="url"></param>
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();
}
/// <summary>
///
/// </summary>
/// <param name="url"></param>
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();
}
/// <summary>
///
/// </summary>
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
}
/// <summary>
/// Implementation for the mock VC
/// </summary>
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; }
/// <summary>
///
/// </summary>
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<bool> IncomingCallFeedbackFunc
{
get { return () => _IncomingCall; }
}
bool _IncomingCall;
protected override Func<bool> MuteFeedbackFunc
{
get { return () => _IsMuted; }
}
bool _IsMuted;
protected override Func<bool> PrivacyModeIsOnFeedbackFunc
{
get { return () => _PrivacyModeIsOn; }
}
bool _PrivacyModeIsOn;
protected override Func<string> SharingSourceFeedbackFunc
{
get { return () => _SharingSource; }
}
string _SharingSource;
protected override Func<int> VolumeLevelFeedbackFunc
{
get { return () => _VolumeLevel; }
}
int _VolumeLevel;
/// <summary>
/// Dials, yo!
/// </summary>
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();
}
/// <summary>
///
/// </summary>
public override void EndCall(CodecActiveCallItem call)
{
Debug.Console(1, this, "EndCall");
ActiveCalls.Remove(call);
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call);
//ActiveCallCountFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
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();
}
/// <summary>
/// For a call from the test methods below
/// </summary>
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
}
/// <summary>
/// For a call from the test methods below
/// </summary>
public override void RejectCall(CodecActiveCallItem call)
{
Debug.Console(1, this, "RejectCall");
ActiveCalls.Remove(call);
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call);
//ActiveCallCountFeedback.FireUpdate();
}
/// <summary>
/// Makes horrible tones go out on the wire!
/// </summary>
/// <param name="s"></param>
public override void SendDtmf(string s)
{
Debug.Console(1, this, "SendDTMF: {0}", s);
}
/// <summary>
///
/// </summary>
public override void StartSharing()
{
}
/// <summary>
///
/// </summary>
public override void StopSharing()
{
}
/// <summary>
/// Called by routing to make it happen
/// </summary>
/// <param name="selector"></param>
public override void ExecuteSwitch(object selector)
{
Debug.Console(1, this, "ExecuteSwitch: {0}", selector);
_SharingSource = selector.ToString();
}
/// <summary>
///
/// </summary>
public override void MuteOff()
{
_IsMuted = false;
MuteFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
public override void MuteOn()
{
_IsMuted = true;
MuteFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
public override void MuteToggle()
{
_IsMuted = !_IsMuted;
MuteFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
/// <param name="level"></param>
public override void SetVolume(ushort level)
{
_VolumeLevel = level;
VolumeLevelFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
/// <param name="pressRelease"></param>
public override void VolumeDown(bool pressRelease)
{
}
/// <summary>
///
/// </summary>
/// <param name="pressRelease"></param>
public override void VolumeUp(bool pressRelease)
{
}
/// <summary>
///
/// </summary>
public override void PrivacyModeOn()
{
Debug.Console(1, this, "PrivacyMuteOn");
if (_PrivacyModeIsOn)
return;
_PrivacyModeIsOn = true;
PrivacyModeIsOnFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
public override void PrivacyModeOff()
{
Debug.Console(1, this, "PrivacyMuteOff");
if (!_PrivacyModeIsOn)
return;
_PrivacyModeIsOn = false;
PrivacyModeIsOnFeedback.FireUpdate();
}
/// <summary>
///
/// </summary>
public override void PrivacyModeToggle()
{
_PrivacyModeIsOn = !_PrivacyModeIsOn;
Debug.Console(1, this, "PrivacyMuteToggle: {0}", _PrivacyModeIsOn);
PrivacyModeIsOnFeedback.FireUpdate();
}
//********************************************************
// SIMULATION METHODS
/// <summary>
///
/// </summary>
/// <param name="url"></param>
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();
}
/// <summary>
///
/// </summary>
/// <param name="url"></param>
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();
}
/// <summary>
///
/// </summary>
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
}
/// <summary>
/// Implementation for the mock VC
/// </summary>
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;
}
}
}

View File

@@ -65,13 +65,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
ActiveCalls = new List<CodecActiveCallItem>();
}
#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;
}
}
/// <summary>
/// Used to track the status of syncronizing the phonebook values when connecting to a codec or refreshing the phonebook info
/// </summary>
public class CodecPhonebookSyncState : IKeyed
{
bool _InitialSyncComplete;
public event EventHandler<EventArgs> 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;
}
}
}