diff --git a/src/PepperDash.Core/Comm/GenericUdpServer.cs b/src/PepperDash.Core/Comm/GenericUdpServer.cs index 61bebf8d..52ac627a 100644 --- a/src/PepperDash.Core/Comm/GenericUdpServer.cs +++ b/src/PepperDash.Core/Comm/GenericUdpServer.cs @@ -131,14 +131,14 @@ namespace PepperDash.Core /// /// /// - /// - public GenericUdpServer(string key, string address, int port, int buffefSize) + /// + public GenericUdpServer(string key, string address, int port, int bufferSize) : base(key) { StreamDebugging = new CommunicationStreamDebugging(key); Hostname = address; Port = port; - BufferSize = buffefSize; + BufferSize = bufferSize; CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); @@ -194,7 +194,21 @@ namespace PepperDash.Core { if (Server == null) { - Server = new UDPServer(); + try + { + var address = IPAddress.Parse(Hostname); + + Server = new UDPServer(address, Port, BufferSize); + + } + catch (Exception ex) + { + this.LogError("Error parsing IP Address '{ipAddress}': message: {message}", Hostname, ex.Message); + this.LogInformation("Creating UDPServer with default buffersize"); + + Server = new UDPServer(); + } + } if (string.IsNullOrEmpty(Hostname)) diff --git a/src/PepperDash.Core/Logging/Debug.cs b/src/PepperDash.Core/Logging/Debug.cs index 37b0f14a..62a95f2c 100644 --- a/src/PepperDash.Core/Logging/Debug.cs +++ b/src/PepperDash.Core/Logging/Debug.cs @@ -40,20 +40,20 @@ namespace PepperDash.Core private static ILogger _logger; - private static readonly LoggingLevelSwitch _consoleLoggingLevelSwitch; + private static readonly LoggingLevelSwitch _consoleLogLevelSwitch; - private static readonly LoggingLevelSwitch _websocketLoggingLevelSwitch; + private static readonly LoggingLevelSwitch _websocketLogLevelSwitch; private static readonly LoggingLevelSwitch _errorLogLevelSwitch; - private static readonly LoggingLevelSwitch _fileLevelSwitch; + private static readonly LoggingLevelSwitch _fileLogLevelSwitch; /// /// Gets the minimum log level for the websocket sink. /// public static LogEventLevel WebsocketMinimumLogLevel { - get { return _websocketLoggingLevelSwitch.MinimumLevel; } + get { return _websocketLogLevelSwitch.MinimumLevel; } } private static readonly DebugWebsocketSink _websocketSink; @@ -138,13 +138,13 @@ namespace PepperDash.Core var defaultFileLogLevel = GetStoredLogEventLevel(FileLevelStoreKey); - _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel); + _consoleLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel); - _websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel); + _websocketLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel); _errorLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultErrorLogLevel); - _fileLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultFileLogLevel); + _fileLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultFileLogLevel); _websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true)); @@ -162,14 +162,14 @@ namespace PepperDash.Core .MinimumLevel.Verbose() .Enrich.FromLogContext() .Enrich.With(new CrestronEnricher()) - .WriteTo.Sink(new DebugConsoleSink(new ExpressionTemplate("[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}")), levelSwitch: _consoleLoggingLevelSwitch) - .WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch) + .WriteTo.Sink(new DebugConsoleSink(new ExpressionTemplate("[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}")), levelSwitch: _consoleLogLevelSwitch) + .WriteTo.Sink(_websocketSink, levelSwitch: _websocketLogLevelSwitch) .WriteTo.Sink(new DebugErrorLogSink(new ExpressionTemplate(errorLogTemplate)), levelSwitch: _errorLogLevelSwitch) .WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath, rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Debug, retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 30 : 60, - levelSwitch: _fileLevelSwitch + levelSwitch: _fileLogLevelSwitch ); try @@ -237,10 +237,13 @@ namespace PepperDash.Core if (DoNotLoadConfigOnNextBoot) CrestronConsole.PrintLine(string.Format("Program {0} will not load config after next boot. Use console command go:{0} to load the config manually", InitialParametersClass.ApplicationNumber)); - _consoleLoggingLevelSwitch.MinimumLevelChanged += (sender, args) => + _errorLogLevelSwitch.MinimumLevelChanged += (sender, args) => { - LogMessage(LogEventLevel.Information, "Console debug level set to {minimumLevel}", _consoleLoggingLevelSwitch.MinimumLevel); + LogMessage(LogEventLevel.Information, "Error log debug level set to {minimumLevel}", _errorLogLevelSwitch.MinimumLevel); }; + + // Set initial error log level based on platform && stored level. If appliance, use stored level, otherwise default to verbose + SetErrorLogMinimumDebugLevel(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? _errorLogLevelSwitch.MinimumLevel : LogEventLevel.Verbose); } /// @@ -273,9 +276,9 @@ namespace PepperDash.Core { CrestronConsole.Print($"Unable to retrieve stored log level for {levelStoreKey}.\r\nError: {result}.\r\nSetting level to {LogEventLevel.Information}\r\n"); - CrestronDataStoreStatic.SetLocalIntValue(levelStoreKey, (int)LogEventLevel.Information); + CrestronDataStoreStatic.SetLocalIntValue(levelStoreKey, levelStoreKey == ErrorLogLevelStoreKey ? (int)LogEventLevel.Warning : (int)LogEventLevel.Information); - return LogEventLevel.Information; + return levelStoreKey == ErrorLogLevelStoreKey ? LogEventLevel.Warning : LogEventLevel.Information; } if (logLevel < 0 || logLevel > 5) @@ -284,6 +287,8 @@ namespace PepperDash.Core return LogEventLevel.Information; } + CrestronConsole.PrintLine($"Stored log level for {levelStoreKey} is {logLevel}"); + return (LogEventLevel)logLevel; } catch (Exception ex) @@ -349,7 +354,11 @@ namespace PepperDash.Core if (levelString.Trim() == "?") { CrestronConsole.ConsoleCommandResponse( - "Used to set the minimum level of debug messages to be printed to the console:\r\n" + + "Used to set the minimum level of debug messages:\r\n" + + "Usage: appdebug:P [sink] [level]\r\n" + + " sink: console (default), errorlog, file, all\r\n" + + " all: sets all sinks to the specified level\r\n" + + " level: 0-5 or LogEventLevel name\r\n" + $"{_logLevels[0]} = 0\r\n" + $"{_logLevels[1]} = 1\r\n" + $"{_logLevels[2]} = 2\r\n" + @@ -361,32 +370,88 @@ namespace PepperDash.Core if (string.IsNullOrEmpty(levelString.Trim())) { - CrestronConsole.ConsoleCommandResponse("AppDebug level = {0}", _consoleLoggingLevelSwitch.MinimumLevel); + CrestronConsole.ConsoleCommandResponse("Console log level = {0}\r\n", _consoleLogLevelSwitch.MinimumLevel); + CrestronConsole.ConsoleCommandResponse("File log level = {0}\r\n", _fileLogLevelSwitch.MinimumLevel); + CrestronConsole.ConsoleCommandResponse("Error log level = {0}\r\n", _errorLogLevelSwitch.MinimumLevel); return; } - if (int.TryParse(levelString, out var levelInt)) + // Parse tokens: first token is sink (defaults to console), second token is level + var tokens = levelString.Trim().Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); + + string sinkName; + string levelToken; + + if (tokens.Length == 1) + { + // Single token - assume it's a level for console sink + sinkName = "console"; + levelToken = tokens[0]; + } + else if (tokens.Length == 2) + { + // Two tokens - first is sink, second is level + sinkName = tokens[0].ToLowerInvariant(); + levelToken = tokens[1]; + } + else + { + CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [sink] [level]"); + return; + } + + // Parse the level using the same logic as before + LogEventLevel level; + + if (int.TryParse(levelToken, out var levelInt)) { if (levelInt < 0 || levelInt > 5) { - CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level. If using a number, value must be between 0-5"); + CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelToken} to valid log level. If using a number, value must be between 0-5"); return; } - SetDebugLevel((uint)levelInt); - return; - } - if (Enum.TryParse(levelString, true, out var levelEnum)) + if (!_logLevels.TryGetValue((uint)levelInt, out level)) + { + level = LogEventLevel.Information; + CrestronConsole.ConsoleCommandResponse($"{levelInt} not valid. Setting level to {level}"); + } + } + else if (Enum.TryParse(levelToken, true, out level)) { - SetDebugLevel(levelEnum); + // Successfully parsed as LogEventLevel enum + } + else + { + CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelToken} to valid log level"); return; } - CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level"); + // Set the level for the specified sink + switch (sinkName) + { + case "console": + SetDebugLevel(level); + break; + case "errorlog": + SetErrorLogMinimumDebugLevel(level); + break; + case "file": + SetFileMinimumDebugLevel(level); + break; + case "all": + SetDebugLevel(level); + SetErrorLogMinimumDebugLevel(level); + SetFileMinimumDebugLevel(level); + break; + default: + CrestronConsole.ConsoleCommandResponse($"Error: Unknown sink '{sinkName}'. Valid sinks: console, errorlog, file"); + break; + } } catch { - CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [0-5]"); + CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [sink] [level]"); } } @@ -416,10 +481,10 @@ namespace PepperDash.Core /// public static void SetDebugLevel(LogEventLevel level) { - _consoleLoggingLevelSwitch.MinimumLevel = level; + _consoleLogLevelSwitch.MinimumLevel = level; - CrestronConsole.ConsoleCommandResponse("[Application {0}], Debug level set to {1}\r\n", - InitialParametersClass.ApplicationNumber, _consoleLoggingLevelSwitch.MinimumLevel); + CrestronConsole.ConsoleCommandResponse("[Application {0}] Debug level set to {1}\r\n", + InitialParametersClass.ApplicationNumber, _consoleLogLevelSwitch.MinimumLevel); CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}"); @@ -436,14 +501,14 @@ namespace PepperDash.Core /// public static void SetWebSocketMinimumDebugLevel(LogEventLevel level) { - _websocketLoggingLevelSwitch.MinimumLevel = level; + _websocketLogLevelSwitch.MinimumLevel = level; var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint)level); if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) LogMessage(LogEventLevel.Information, "Error saving websocket debug level setting: {erro}", err); - LogMessage(LogEventLevel.Information, "Websocket debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel); + LogMessage(LogEventLevel.Information, "Websocket debug level set to {0}", _websocketLogLevelSwitch.MinimumLevel); } /// @@ -453,12 +518,17 @@ namespace PepperDash.Core { _errorLogLevelSwitch.MinimumLevel = level; - var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level); + CrestronConsole.ConsoleCommandResponse("[Application {0}] Error log level set to {1}\r\n", + InitialParametersClass.ApplicationNumber, _errorLogLevelSwitch.MinimumLevel); + + CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}"); + + var err = CrestronDataStoreStatic.SetLocalIntValue(ErrorLogLevelStoreKey, (int)level); + + CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}"); if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - LogMessage(LogEventLevel.Information, "Error saving Error Log debug level setting: {error}", err); - - LogMessage(LogEventLevel.Information, "Error log debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel); + CrestronConsole.PrintLine($"Error saving error log debug level setting: {err}"); } /// @@ -466,14 +536,19 @@ namespace PepperDash.Core /// public static void SetFileMinimumDebugLevel(LogEventLevel level) { - _errorLogLevelSwitch.MinimumLevel = level; + _fileLogLevelSwitch.MinimumLevel = level; - var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level); + CrestronConsole.ConsoleCommandResponse("[Application {0}] File log level set to {1}\r\n", + InitialParametersClass.ApplicationNumber, _fileLogLevelSwitch.MinimumLevel); + + CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}"); + + var err = CrestronDataStoreStatic.SetLocalIntValue(FileLevelStoreKey, (int)level); + + CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}"); if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - LogMessage(LogEventLevel.Information, "Error saving File debug level setting: {error}", err); - - LogMessage(LogEventLevel.Information, "File debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel); + CrestronConsole.PrintLine($"Error saving file debug level setting: {err}"); } /// diff --git a/src/PepperDash.Essentials.Devices.Common/Audio/GenericAudioOut.cs b/src/PepperDash.Essentials.Devices.Common/Audio/GenericAudioOut.cs index 23f46007..c0f8ac1e 100644 --- a/src/PepperDash.Essentials.Devices.Common/Audio/GenericAudioOut.cs +++ b/src/PepperDash.Essentials.Devices.Common/Audio/GenericAudioOut.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; +using System.Collections.Generic; using PepperDash.Core; using PepperDash.Essentials.Core; @@ -17,48 +13,68 @@ namespace PepperDash.Essentials.Devices.Common /// public class GenericAudioOut : EssentialsDevice, IRoutingSink { - public RoutingInputPort CurrentInputPort => AnyAudioIn; + /// + /// Gets the current input port + /// + public RoutingInputPort CurrentInputPort => AnyAudioIn; - public event SourceInfoChangeHandler CurrentSourceChange; + /// + /// Event fired when the current source changes + /// + public event SourceInfoChangeHandler CurrentSourceChange; - public string CurrentSourceInfoKey { get; set; } - public SourceListItem CurrentSourceInfo - { - get - { - return _CurrentSourceInfo; - } - set - { - if (value == _CurrentSourceInfo) return; + /// + /// Gets or sets the current source info key + /// + public string CurrentSourceInfoKey { get; set; } + /// + /// Gets or sets the current source info + /// + public SourceListItem CurrentSourceInfo + { + get + { + return _CurrentSourceInfo; + } + set + { + if (value == _CurrentSourceInfo) return; - var handler = CurrentSourceChange; + var handler = CurrentSourceChange; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.WillChange); + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.WillChange); - _CurrentSourceInfo = value; + _CurrentSourceInfo = value; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.DidChange); - } - } - SourceListItem _CurrentSourceInfo; + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.DidChange); + } + } + SourceListItem _CurrentSourceInfo; - /// - /// Gets or sets the AnyAudioIn - /// + /// + /// Gets or sets the AnyAudioIn + /// public RoutingInputPort AnyAudioIn { get; private set; } + /// + /// Constructor for GenericAudioOut + /// + /// Device key + /// Device name public GenericAudioOut(string key, string name) : base(key, name) { - AnyAudioIn = new RoutingInputPort(RoutingPortNames.AnyAudioIn, eRoutingSignalType.Audio, + AnyAudioIn = new RoutingInputPort(RoutingPortNames.AnyAudioIn, eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio, null, this); } #region IRoutingInputs Members + /// + /// Gets the collection of input ports + /// public RoutingPortCollection InputPorts { get { return new RoutingPortCollection { AnyAudioIn }; } @@ -68,23 +84,32 @@ namespace PepperDash.Essentials.Devices.Common } - /// - /// Represents a GenericAudioOutWithVolume - /// + /// + /// Represents a GenericAudioOutWithVolume + /// public class GenericAudioOutWithVolume : GenericAudioOut, IHasVolumeDevice { + /// + /// Gets the volume device key + /// public string VolumeDeviceKey { get; private set; } + /// + /// Gets the volume zone + /// public uint VolumeZone { get; private set; } + /// + /// Gets the volume device + /// public IBasicVolumeControls VolumeDevice - { + { get { var dev = DeviceManager.GetDeviceForKey(VolumeDeviceKey); if (dev is IAudioZones) return (dev as IAudioZones).Zone[VolumeZone]; else return dev as IBasicVolumeControls; - } + } } /// @@ -103,24 +128,30 @@ namespace PepperDash.Essentials.Devices.Common } - public class GenericAudioOutWithVolumeFactory : EssentialsDeviceFactory - { - public GenericAudioOutWithVolumeFactory() - { - TypeNames = new List() { "genericaudiooutwithvolume" }; - } + /// + /// Factory for creating GenericAudioOutWithVolume devices + /// + public class GenericAudioOutWithVolumeFactory : EssentialsDeviceFactory + { + /// + /// Constructor for GenericAudioOutWithVolumeFactory + /// + public GenericAudioOutWithVolumeFactory() + { + TypeNames = new List() { "genericaudiooutwithvolume" }; + } - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new GenericAudioOutWithVolumeFactory Device"); - var zone = dc.Properties.Value("zone"); - return new GenericAudioOutWithVolume(dc.Key, dc.Name, - dc.Properties.Value("volumeDeviceKey"), zone); - } - } + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new GenericAudioOutWithVolumeFactory Device"); + var zone = dc.Properties.Value("zone"); + return new GenericAudioOutWithVolume(dc.Key, dc.Name, + dc.Properties.Value("volumeDeviceKey"), zone); + } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/AudioCodecBase.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/AudioCodecBase.cs index c0eff735..7f760bc3 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/AudioCodecBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/AudioCodecBase.cs @@ -1,18 +1,20 @@ 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.Devices.Common.Codec; namespace PepperDash.Essentials.Devices.Common.AudioCodec { + /// + /// Abstract base class for audio codec devices + /// public abstract class AudioCodecBase : EssentialsDevice, IHasDialer, IUsageTracking, IAudioCodecInfo { + /// + /// Event fired when call status changes + /// public event EventHandler CallStatusChange; /// @@ -52,6 +54,11 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec /// public List ActiveCalls { get; set; } + /// + /// Constructor for AudioCodecBase + /// + /// Device key + /// Device name public AudioCodecBase(string key, string name) : base(key, name) { @@ -70,11 +77,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec } /// - /// + /// Handles call status change events /// - /// - /// - /// + /// The call item that changed status protected void OnCallStatusChange(CodecActiveCallItem item) { var handler = CallStatusChange; @@ -92,16 +97,22 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec #region IHasDialer Members + /// public abstract void Dial(string number); + /// public abstract void EndCall(CodecActiveCallItem activeCall); + /// public abstract void EndAllCalls(); + /// public abstract void AcceptCall(CodecActiveCallItem item); + /// public abstract void RejectCall(CodecActiveCallItem item); + /// public abstract void SendDtmf(string digit); #endregion diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IAudioCodecInfo.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IAudioCodecInfo.cs index e853c898..3e6b0418 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IAudioCodecInfo.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IAudioCodecInfo.cs @@ -1,16 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Essentials.Devices.Common.AudioCodec +namespace PepperDash.Essentials.Devices.Common.AudioCodec { /// /// Implements a common set of data about a codec /// public interface IAudioCodecInfo { + /// + /// Gets the codec information + /// AudioCodecInfo CodecInfo { get; } } @@ -19,6 +16,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec /// public abstract class AudioCodecInfo { + /// + /// Gets or sets the phone number + /// public abstract string PhoneNumber { get; set; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IHasAudioCodec.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IHasAudioCodec.cs index a1a2d64d..946c2053 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IHasAudioCodec.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IHasAudioCodec.cs @@ -1,23 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.AudioCodec { /// /// For rooms that have audio codec /// - public interface IHasAudioCodec:IHasInCallFeedback + public interface IHasAudioCodec : IHasInCallFeedback { + /// + /// Gets the audio codec device + /// AudioCodecBase AudioCodec { get; } - /// - /// Make this more specific - /// //List ActiveCalls { get; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs index 85c21474..48235a45 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; +using System.Collections.Generic; using PepperDash.Core; using PepperDash.Essentials.Core; @@ -17,6 +13,12 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec /// public class MockAC : AudioCodecBase { + /// + /// Constructor for MockAC + /// + /// Device key + /// Device name + /// MockAC properties configuration public MockAC(string key, string name, MockAcPropertiesConfig props) : base(key, name) { @@ -109,13 +111,10 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec Debug.LogMessage(LogEventLevel.Debug, this, "BEEP BOOP SendDTMF: {0}", s); } - /// - /// - /// - /// /// /// TestIncomingAudioCall method /// + /// Phone number to call from public void TestIncomingAudioCall(string number) { Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingAudioCall from {0}", number); @@ -133,6 +132,7 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec { string _phoneNumber; + /// public override string PhoneNumber { get @@ -151,6 +151,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec /// public class MockACFactory : EssentialsDeviceFactory { + /// + /// Constructor for MockACFactory + /// public MockACFactory() { TypeNames = new List() { "mockac" }; diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAcPropertiesConfig.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAcPropertiesConfig.cs index 5ac31dcc..0deaca97 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAcPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAcPropertiesConfig.cs @@ -1,12 +1,4 @@ - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using Newtonsoft.Json; +using Newtonsoft.Json; namespace PepperDash.Essentials.Devices.Common.AudioCodec { @@ -15,10 +7,10 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec /// public class MockAcPropertiesConfig { - [JsonProperty("phoneNumber")] /// /// Gets or sets the PhoneNumber /// + [JsonProperty("phoneNumber")] public string PhoneNumber { get; set; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs index 0fb6f6ca..e2e15668 100644 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs @@ -3,20 +3,14 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Crestron.SimplSharp; -using System.Reflection; using Crestron.SimplSharpPro.DeviceSupport; +using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Devices; -using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.Devices; using PepperDash.Essentials.Core.Presets; -using PepperDash.Essentials.Devices.Common.Codec; - -using Newtonsoft.Json; using Serilog.Events; namespace PepperDash.Essentials.Devices.Common.Cameras @@ -26,31 +20,52 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public enum eCameraCapabilities { + /// + /// No camera capabilities + /// None = 0, + /// + /// Camera supports pan movement + /// Pan = 1, - Tilt = 2, + /// + /// Camera supports tilt movement + /// + Tilt = 2, + /// + /// Camera supports zoom functionality + /// Zoom = 4, + /// + /// Camera supports focus adjustment + /// Focus = 8 } + /// + /// Abstract base class for camera devices that provides common camera functionality and capabilities + /// public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs - { - [JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)] + { /// /// Gets or sets the ControlMode /// + [JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)] public eCameraControlMode ControlMode { get; protected set; } #region IRoutingOutputs Members - [JsonIgnore] /// /// Gets or sets the OutputPorts /// + [JsonIgnore] public RoutingPortCollection OutputPorts { get; protected set; } #endregion + /// + /// Gets a value indicating whether this camera supports pan movement + /// [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)] public bool CanPan { @@ -59,6 +74,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan; } } + + /// + /// Gets a value indicating whether this camera supports tilt movement + /// [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)] public bool CanTilt { @@ -67,6 +86,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt; } } + + /// + /// Gets a value indicating whether this camera supports zoom functionality + /// [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)] public bool CanZoom { @@ -75,6 +98,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom; } } + + /// + /// Gets a value indicating whether this camera supports focus adjustment + /// [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)] public bool CanFocus { @@ -84,23 +111,42 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } } - // A bitmasked value to indicate the movement capabilites of this camera + /// + /// Gets or sets a bitmasked value to indicate the movement capabilities of this camera + /// protected eCameraCapabilities Capabilities { get; set; } - protected CameraBase(DeviceConfig config) : base(config) - { - OutputPorts = new RoutingPortCollection(); - - ControlMode = eCameraControlMode.Manual; - - } - - protected CameraBase(string key, string name) : - this (new DeviceConfig{Name = name, Key = key}) + /// + /// Initializes a new instance of the CameraBase class with the specified device configuration + /// + /// The device configuration + protected CameraBase(DeviceConfig config) : base(config) { - + OutputPorts = new RoutingPortCollection(); + + ControlMode = eCameraControlMode.Manual; + } + /// + /// Initializes a new instance of the CameraBase class with the specified key and name + /// + /// The unique key for this camera device + /// The friendly name for this camera device + protected CameraBase(string key, string name) : + this(new DeviceConfig { Name = name, Key = key }) + { + + } + + /// + /// Links the camera device to the API bridge for control and feedback + /// + /// The camera device to link + /// The trilist for communication + /// The starting join number for the camera controls + /// The join map key for custom join mappings + /// The EiscApiAdvanced bridge for advanced join mapping protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { @@ -240,13 +286,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { int tempNum = i; - trilist.SetSigTrueAction((ushort) (joinMap.PresetRecallStart.JoinNumber + tempNum), () => + trilist.SetSigTrueAction((ushort)(joinMap.PresetRecallStart.JoinNumber + tempNum), () => { presetsCamera.PresetSelect(tempNum); }); - trilist.SetSigTrueAction((ushort) (joinMap.PresetSaveStart.JoinNumber + tempNum), () => + trilist.SetSigTrueAction((ushort)(joinMap.PresetSaveStart.JoinNumber + tempNum), () => { - var label = trilist.GetString((ushort) (joinMap.PresetLabelStart.JoinNumber + tempNum)); + var label = trilist.GetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum)); presetsCamera.PresetStore(tempNum, label); }); @@ -277,7 +323,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label); } } - } + } /// @@ -285,6 +331,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public class CameraPreset : PresetBase { + /// + /// Initializes a new instance of the CameraPreset class + /// + /// The preset ID + /// The preset description + /// Whether the preset is defined + /// Whether the preset can be defined public CameraPreset(int id, string description, bool isDefined, bool isDefinable) : base(id, description, isDefined, isDefinable) { @@ -293,37 +346,37 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } - /// - /// Represents a CameraPropertiesConfig - /// - public class CameraPropertiesConfig - { - /// - /// Gets or sets the CommunicationMonitorProperties - /// - public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } + /// + /// Represents a CameraPropertiesConfig + /// + public class CameraPropertiesConfig + { + /// + /// Gets or sets the CommunicationMonitorProperties + /// + public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } - /// - /// Gets or sets the Control - /// - public ControlPropertiesConfig Control { get; set; } + /// + /// Gets or sets the Control + /// + public ControlPropertiesConfig Control { get; set; } - [JsonProperty("supportsAutoMode")] /// /// Gets or sets the SupportsAutoMode /// + [JsonProperty("supportsAutoMode")] public bool SupportsAutoMode { get; set; } - [JsonProperty("supportsOffMode")] /// /// Gets or sets the SupportsOffMode /// + [JsonProperty("supportsOffMode")] public bool SupportsOffMode { get; set; } - [JsonProperty("presets")] /// /// Gets or sets the Presets /// + [JsonProperty("presets")] public List Presets { get; set; } - } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs deleted file mode 100644 index cec2f58b..00000000 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs +++ /dev/null @@ -1,326 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using PepperDash.Core; -using PepperDash.Essentials.Core; - -namespace PepperDash.Essentials.Devices.Common.Cameras -{ - /// - /// Enum for camera control modes - /// - public enum eCameraControlMode - { - /// - /// Manual control mode, where the camera is controlled directly by the user or system - /// - Manual = 0, - /// - /// Off control mode, where the camera is turned off or disabled - /// - Off, - /// - /// Auto control mode, where the camera automatically adjusts settings based on the environment or conditions - /// - Auto - } - - - /// - /// Interface for devices that have cameras - /// - public interface IHasCameras : IKeyName - { - /// - /// Event that is raised when a camera is selected - /// - event EventHandler CameraSelected; - - /// - /// List of cameras on the device. This should be a list of CameraBase objects - /// - List Cameras { get; } - - /// - /// The currently selected camera. This should be a CameraBase object - /// - CameraBase SelectedCamera { get; } - - /// - /// Feedback that indicates the currently selected camera - /// - StringFeedback SelectedCameraFeedback { get; } - - /// - /// Selects a camera from the list of available cameras based on the provided key. - /// - /// The unique identifier or name of the camera to select. - void SelectCamera(string key); - } - - /// - /// Defines the contract for IHasCodecCameras - /// - public interface IHasCodecCameras : IHasCameras, IHasFarEndCameraControl - { - - } - - /// - /// To be implmented on codecs that can disable their camera(s) to blank the near end video - /// - public interface IHasCameraOff - { - /// - /// Feedback that indicates whether the camera is off - /// - BoolFeedback CameraIsOffFeedback { get; } - - /// - /// Turns the camera off, blanking the near end video - /// - void CameraOff(); - } - - /// - /// Describes the ability to mute and unmute camera video - /// - public interface IHasCameraMute - { - /// - /// Feedback that indicates whether the camera is muted - /// - BoolFeedback CameraIsMutedFeedback { get; } - - /// - /// Mutes the camera video, preventing it from being sent to the far end - /// - void CameraMuteOn(); - - /// - /// Unmutes the camera video, allowing it to be sent to the far end - /// - void CameraMuteOff(); - - /// - /// Toggles the camera mute state. If the camera is muted, it will be unmuted, and vice versa. - /// - void CameraMuteToggle(); - } - - /// - /// Interface for devices that can mute and unmute their camera video, with an event for unmute requests - /// - public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute - { - /// - /// Event that is raised when a video unmute is requested, typically by the far end - /// - event EventHandler VideoUnmuteRequested; - } - - /// - /// Event arguments for the CameraSelected event - /// - public class CameraSelectedEventArgs : EventArgs - { - /// - /// Gets or sets the SelectedCamera - /// - public CameraBase SelectedCamera { get; private set; } - - /// - /// Constructor for CameraSelectedEventArgs - /// - /// - public CameraSelectedEventArgs(CameraBase camera) - { - SelectedCamera = camera; - } - } - - /// - /// Interface for devices that have a far end camera control - /// - public interface IHasFarEndCameraControl - { - /// - /// Gets the far end camera, which is typically a CameraBase object that represents the camera at the far end of a call - /// - CameraBase FarEndCamera { get; } - - /// - /// Feedback that indicates whether the far end camera is being controlled - /// - BoolFeedback ControllingFarEndCameraFeedback { get; } - - } - - /// - /// Defines the contract for IAmFarEndCamera - /// - public interface IAmFarEndCamera - { - - } - - /// - /// Interface for devices that have camera controls - /// - public interface IHasCameraControls - { - } - - /// - /// Defines the contract for IHasCameraPtzControl - /// - public interface IHasCameraPtzControl : IHasCameraPanControl, IHasCameraTiltControl, IHasCameraZoomControl - { - /// - /// Resets the camera position - /// - void PositionHome(); - } - - /// - /// Interface for camera pan control - /// - public interface IHasCameraPanControl : IHasCameraControls - { - /// - /// Pans the camera left - /// - void PanLeft(); - - /// - /// Pans the camera right - /// - void PanRight(); - - /// - /// Stops the camera pan movement - /// - void PanStop(); - } - - /// - /// Defines the contract for IHasCameraTiltControl - /// - public interface IHasCameraTiltControl : IHasCameraControls - { - /// - /// Tilts the camera down - /// - void TiltDown(); - - /// - /// Tilts the camera up - /// - void TiltUp(); - - /// - /// Stops the camera tilt movement - /// - void TiltStop(); - } - - /// - /// Defines the contract for IHasCameraZoomControl - /// - public interface IHasCameraZoomControl : IHasCameraControls - { - /// - /// Zooms the camera in - /// - void ZoomIn(); - - /// - /// Zooms the camera out - /// - void ZoomOut(); - - /// - /// Stops the camera zoom movement - /// - void ZoomStop(); - } - - /// - /// Defines the contract for IHasCameraFocusControl - /// - public interface IHasCameraFocusControl : IHasCameraControls - { - /// - /// Focuses the camera near - /// - void FocusNear(); - - /// - /// Focuses the camera far - /// - void FocusFar(); - - /// - /// Stops the camera focus movement - /// - void FocusStop(); - - /// - /// Triggers the camera's auto focus functionality, if available. - /// - void TriggerAutoFocus(); - } - - /// - /// Interface for devices that have auto focus mode control - /// - public interface IHasAutoFocusMode - { - /// - /// Sets the focus mode to auto or manual, or toggles between them. - /// - void SetFocusModeAuto(); - - /// - /// Sets the focus mode to manual, allowing for manual focus adjustments. - /// - void SetFocusModeManual(); - - /// - /// Toggles the focus mode between auto and manual. - /// - void ToggleFocusMode(); - } - - /// - /// Interface for devices that have camera auto mode control - /// - public interface IHasCameraAutoMode : IHasCameraControls - { - /// - /// Enables or disables the camera's auto mode, which may include automatic adjustments for focus, exposure, and other settings. - /// - void CameraAutoModeOn(); - - /// - /// Disables the camera's auto mode, allowing for manual control of camera settings. - /// - void CameraAutoModeOff(); - - /// - /// Toggles the camera's auto mode state. If the camera is in auto mode, it will switch to manual mode, and vice versa. - /// - void CameraAutoModeToggle(); - - /// - /// Feedback that indicates whether the camera's auto mode is currently enabled. - /// - BoolFeedback CameraAutoModeIsOnFeedback { get; } - } - - - - -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs index 9a8bce8b..126bcd27 100644 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs @@ -3,38 +3,33 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro.DeviceSupport; +using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Devices.Common.Codec; -using System.Text.RegularExpressions; -using System.Reflection; - -using Newtonsoft.Json; using Serilog.Events; namespace PepperDash.Essentials.Devices.Common.Cameras { - /// - /// Represents a CameraVisca - /// - public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode - { + /// + /// Represents a CameraVisca + /// + public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode + { private readonly CameraViscaPropertiesConfig PropertiesConfig; - /// - /// Gets or sets the Communication - /// - public IBasicCommunication Communication { get; private set; } + /// + /// Gets or sets the Communication + /// + public IBasicCommunication Communication { get; private set; } - /// - /// Gets or sets the CommunicationMonitor - /// - public StatusMonitorBase CommunicationMonitor { get; private set; } + /// + /// Gets or sets the CommunicationMonitor + /// + public StatusMonitorBase CommunicationMonitor { get; private set; } /// /// Used to store the actions to parse inquiry responses as the inquiries are sent @@ -45,20 +40,41 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// Camera ID (Default 1) /// public byte ID = 0x01; + + /// + /// Response ID used for VISCA communication + /// public byte ResponseID; + /// + /// Slow speed value for pan movement + /// + public byte PanSpeedSlow = 0x10; - public byte PanSpeedSlow = 0x10; - public byte TiltSpeedSlow = 0x10; + /// + /// Slow speed value for tilt movement + /// + public byte TiltSpeedSlow = 0x10; + /// + /// Fast speed value for pan movement + /// public byte PanSpeedFast = 0x13; + + /// + /// Fast speed value for tilt movement + /// public byte TiltSpeedFast = 0x13; // private bool IsMoving; - private bool IsZooming; + private bool IsZooming; bool _powerIsOn; - public bool PowerIsOn + + /// + /// Gets or sets a value indicating whether the camera power is on + /// + public bool PowerIsOn { get { @@ -87,12 +103,23 @@ namespace PepperDash.Essentials.Devices.Common.Cameras long FastSpeedHoldTimeMs = 2000; - byte[] IncomingBuffer = new byte[] { }; - public BoolFeedback PowerIsOnFeedback { get; private set; } + byte[] IncomingBuffer = new byte[] { }; + /// + /// Feedback indicating whether the camera power is on + /// + public BoolFeedback PowerIsOnFeedback { get; private set; } + + /// + /// Initializes a new instance of the CameraVisca class + /// + /// The unique key for this camera device + /// The friendly name for this camera device + /// The communication interface for VISCA protocol + /// The camera properties configuration public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) : - base(key, name) - { + base(key, name) + { InquiryResponseQueue = new CrestronQueue>(15); Presets = props.Presets; @@ -107,8 +134,8 @@ namespace PepperDash.Essentials.Devices.Common.Cameras OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true)); // Default to all capabilties - Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus; - + Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus; + Communication = comm; if (comm is ISocketStatus socket) { @@ -121,19 +148,19 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } Communication.BytesReceived += new EventHandler(Communication_BytesReceived); - PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; }); - CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; }); + PowerIsOnFeedback = new BoolFeedback("powerIsOn", () => { return PowerIsOn; }); + CameraIsOffFeedback = new BoolFeedback("cameraIsOff", () => { return !PowerIsOn; }); - if (props.CommunicationMonitorProperties != null) - { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties); - } - else - { - CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF"); - } - DeviceManager.AddDevice(CommunicationMonitor); - } + if (props.CommunicationMonitorProperties != null) + { + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties); + } + else + { + CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF"); + } + DeviceManager.AddDevice(CommunicationMonitor); + } /// @@ -165,57 +192,57 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } } - /// - /// CustomActivate method - /// - /// - public override bool CustomActivate() - { - Communication.Connect(); - - - CommunicationMonitor.StatusChange += (o, a) => { Debug.LogMessage(LogEventLevel.Verbose, this, "Communication monitor state: {0}", CommunicationMonitor.Status); }; - CommunicationMonitor.Start(); + /// + /// CustomActivate method + /// + /// + public override bool CustomActivate() + { + Communication.Connect(); - CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator); - return true; - } + CommunicationMonitor.StatusChange += (o, a) => { Debug.LogMessage(LogEventLevel.Verbose, this, "Communication monitor state: {0}", CommunicationMonitor.Status); }; + CommunicationMonitor.Start(); - /// - /// LinkToApi method - /// - public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge); - } - void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString()); + CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator); + return true; + } - if (e.Client.IsConnected) - { - - } - else - { + /// + /// LinkToApi method + /// + public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge); + } - } - } - + void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString()); - void SendBytes(byte[] b) - { - - if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 - Debug.LogMessage(LogEventLevel.Verbose, this, "Sending:{0}", ComTextHelper.GetEscapedText(b)); + if (e.Client.IsConnected) + { - Communication.SendBytes(b); - } + } + else + { - void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) - { + } + } + + + void SendBytes(byte[] b) + { + + if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 + Debug.LogMessage(LogEventLevel.Verbose, this, "Sending:{0}", ComTextHelper.GetEscapedText(b)); + + Communication.SendBytes(b); + } + + void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) + { var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length]; try @@ -355,10 +382,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// /// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed. /// - /// - /// - private void SendPanTiltCommand (byte[] cmd, bool fastSpeedEnabled) - { + /// The VISCA command to send + /// Whether fast speed is enabled for this command + private void SendPanTiltCommand(byte[] cmd, bool fastSpeedEnabled) + { SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled)); if (!fastSpeedEnabled) @@ -372,7 +399,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs); } - } + } private void StopSpeedTimer() { @@ -381,7 +408,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras SpeedTimer.Stop(); SpeedTimer.Dispose(); SpeedTimer = null; - } + } } /// @@ -424,14 +451,14 @@ namespace PepperDash.Essentials.Devices.Common.Cameras InquiryResponseQueue.Enqueue(HandlePowerResponse); } - /// - /// PowerOn method - /// - public void PowerOn() - { - SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF }); + /// + /// PowerOn method + /// + public void PowerOn() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF }); SendPowerQuery(); - } + } void HandlePowerResponse(byte[] response) { @@ -450,12 +477,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } } - /// - /// PowerOff method - /// - public void PowerOff() - { - SendBytes(new byte[] {ID, 0x01, 0x04, 0x00, 0x03, 0xFF}); + /// + /// PowerOff method + /// + public void PowerOff() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x03, 0xFF }); SendPowerQuery(); } @@ -470,22 +497,22 @@ namespace PepperDash.Essentials.Devices.Common.Cameras PowerOn(); } - /// - /// PanLeft method - /// - public void PanLeft() - { - SendPanTiltCommand(new byte[] {0x01, 0x03}, false); - // IsMoving = true; - } - /// - /// PanRight method - /// - public void PanRight() - { + /// + /// PanLeft method + /// + public void PanLeft() + { + SendPanTiltCommand(new byte[] { 0x01, 0x03 }, false); + // IsMoving = true; + } + /// + /// PanRight method + /// + public void PanRight() + { SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false); - // IsMoving = true; - } + // IsMoving = true; + } /// /// PanStop method /// @@ -493,22 +520,22 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { Stop(); } - /// - /// TiltDown method - /// - public void TiltDown() - { + /// + /// TiltDown method + /// + public void TiltDown() + { SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false); - // IsMoving = true; - } - /// - /// TiltUp method - /// - public void TiltUp() - { + // IsMoving = true; + } + /// + /// TiltUp method + /// + public void TiltUp() + { SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false); - // IsMoving = true; - } + // IsMoving = true; + } /// /// TiltStop method /// @@ -517,28 +544,28 @@ namespace PepperDash.Essentials.Devices.Common.Cameras Stop(); } - private void SendZoomCommand (byte cmd) - { - SendBytes(new byte[] {ID, 0x01, 0x04, 0x07, cmd, 0xFF} ); - } + private void SendZoomCommand(byte cmd) + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x07, cmd, 0xFF }); + } - /// - /// ZoomIn method - /// - public void ZoomIn() - { + /// + /// ZoomIn method + /// + public void ZoomIn() + { SendZoomCommand(ZoomInCmd); - IsZooming = true; - } - /// - /// ZoomOut method - /// - public void ZoomOut() - { + IsZooming = true; + } + /// + /// ZoomOut method + /// + public void ZoomOut() + { SendZoomCommand(ZoomOutCmd); - IsZooming = true; - } + IsZooming = true; + } /// /// ZoomStop method /// @@ -547,23 +574,23 @@ namespace PepperDash.Essentials.Devices.Common.Cameras Stop(); } - /// - /// Stop method - /// - public void Stop() - { - if (IsZooming) - { + /// + /// Stop method + /// + public void Stop() + { + if (IsZooming) + { SendZoomCommand(ZoomStopCmd); - IsZooming = false; - } - else - { + IsZooming = false; + } + else + { StopSpeedTimer(); SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false); - // IsMoving = false; - } - } + // IsMoving = false; + } + } /// /// PositionHome method /// @@ -572,33 +599,39 @@ namespace PepperDash.Essentials.Devices.Common.Cameras SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }); SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF }); } - /// - /// RecallPreset method - /// - public void RecallPreset(int presetNumber) - { - SendBytes(new byte[] {ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} ); - } - /// - /// SavePreset method - /// - public void SavePreset(int presetNumber) - { - SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF }); - } + /// + /// RecallPreset method + /// + public void RecallPreset(int presetNumber) + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF }); + } + /// + /// SavePreset method + /// + public void SavePreset(int presetNumber) + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF }); + } #region IHasCameraPresets Members + /// + /// Event that is raised when the presets list has changed + /// public event EventHandler PresetsListHasChanged; - protected void OnPresetsListHasChanged() - { - var handler = PresetsListHasChanged; - if (handler == null) - return; + /// + /// Raises the PresetsListHasChanged event + /// + protected void OnPresetsListHasChanged() + { + var handler = PresetsListHasChanged; + if (handler == null) + return; - handler.Invoke(this, EventArgs.Empty); - } + handler.Invoke(this, EventArgs.Empty); + } /// /// Gets or sets the Presets @@ -741,6 +774,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public class CameraViscaFactory : EssentialsDeviceFactory { + /// + /// Initializes a new instance of the CameraViscaFactory class + /// public CameraViscaFactory() { TypeNames = new List() { "cameravisca" }; @@ -768,11 +804,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { /// /// Control ID of the camera (1-7) - /// - [JsonProperty("id")] - /// /// Gets or sets the Id /// + [JsonProperty("id")] public uint Id { get; set; } /// @@ -790,7 +824,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// /// Slow tilt speed (0-18) /// - [JsonProperty("tiltSpeedSlow")] + [JsonProperty("tiltSpeedSlow")] public uint TiltSpeedSlow { get; set; } /// diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/IHasCameraPresets.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/IHasCameraPresets.cs index a8e8983d..0234a405 100644 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/IHasCameraPresets.cs +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/IHasCameraPresets.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; namespace PepperDash.Essentials.Devices.Common.Cameras { @@ -11,12 +8,27 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public interface IHasCameraPresets { + /// + /// Event that is raised when the presets list has changed + /// event EventHandler PresetsListHasChanged; + /// + /// Gets the list of camera presets + /// List Presets { get; } + /// + /// Selects the specified preset + /// + /// The preset number to select void PresetSelect(int preset); + /// + /// Stores a preset at the specified location with the given description + /// + /// The preset number to store + /// The description for the preset void PresetStore(int preset, string description); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/CameraSelectedEventArgs.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/CameraSelectedEventArgs.cs new file mode 100644 index 00000000..bb2a85a2 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/CameraSelectedEventArgs.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Event arguments for the CameraSelected event + /// + [Obsolete("Use CameraSelectedEventArgs instead. This class will be removed in a future version")] + public class CameraSelectedEventArgs : EventArgs + { + /// Gets or sets the SelectedCamera + /// + public CameraBase SelectedCamera { get; private set; } + + /// + /// Constructor for CameraSelectedEventArgs + /// + /// + public CameraSelectedEventArgs(CameraBase camera) + { + SelectedCamera = camera; + } + } + + /// + /// Event arguments for the CameraSelected event + /// + /// + public class CameraSelectedEventArgs : EventArgs + { + /// + /// Gets or sets the SelectedCamera + /// + public T SelectedCamera { get; private set; } + + /// + /// Constructor for CameraSelectedEventArgs + /// + /// + public CameraSelectedEventArgs(T camera) + { + SelectedCamera = camera; + } + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IAmFarEndCamera.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IAmFarEndCamera.cs new file mode 100644 index 00000000..a8e96664 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IAmFarEndCamera.cs @@ -0,0 +1,12 @@ +using PepperDash.Core; + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Defines the contract for IAmFarEndCamera + /// + public interface IAmFarEndCamera : IKeyName + { + + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/ICameraCapabilities.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/ICameraCapabilities.cs new file mode 100644 index 00000000..cf39a95c --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/ICameraCapabilities.cs @@ -0,0 +1,86 @@ +using Newtonsoft.Json; +using PepperDash.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Interface for camera capabilities + /// + public interface ICameraCapabilities: IKeyName + { + /// + /// Indicates whether the camera can pan + /// + [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)] + bool CanPan { get; } + + /// + /// Indicates whether the camera can tilt + /// + [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)] + bool CanTilt { get; } + + /// + /// Indicates whether the camera can zoom + /// + [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)] + bool CanZoom { get; } + + + /// + /// Indicates whether the camera can focus + /// + [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)] + bool CanFocus { get; } + } + + /// + /// Indicates the capabilities of a camera + /// + public class CameraCapabilities : ICameraCapabilities + { + + /// + /// Unique Key + /// + [JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)] + public string Key { get; set; } + + /// + /// Isn't it obvious :) + /// + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public string Name { get; set; } + + + /// + /// Indicates whether the camera can pan + /// + [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)] + public bool CanPan { get; set; } + + /// + /// Indicates whether the camera can tilt + /// + [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)] + public bool CanTilt { get; set; } + + /// + /// Indicates whether the camera can zoom + /// + [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)] + public bool CanZoom { get; set; } + + + /// + /// Indicates whether the camera can focus + /// + [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)] + public bool CanFocus { get; set; } + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasAutoFocusMode.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasAutoFocusMode.cs new file mode 100644 index 00000000..0dbd5f52 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasAutoFocusMode.cs @@ -0,0 +1,24 @@ + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Interface for devices that have auto focus mode control + /// + public interface IHasAutoFocusMode : IHasCameraControls + { + /// + /// Sets the focus mode to auto or manual, or toggles between them. + /// + void SetFocusModeAuto(); + + /// + /// Sets the focus mode to manual, allowing for manual focus adjustments. + /// + void SetFocusModeManual(); + + /// + /// Toggles the focus mode between auto and manual. + /// + void ToggleFocusMode(); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraAutoMode.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraAutoMode.cs new file mode 100644 index 00000000..9eeb1f40 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraAutoMode.cs @@ -0,0 +1,31 @@ +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + + /// + /// Interface for devices that have camera auto mode control + /// + public interface IHasCameraAutoMode : IHasCameraControls + { + /// + /// Enables or disables the camera's auto mode, which may include automatic adjustments for focus, exposure, and other settings. + /// + void CameraAutoModeOn(); + + /// + /// Disables the camera's auto mode, allowing for manual control of camera settings. + /// + void CameraAutoModeOff(); + + /// + /// Toggles the camera's auto mode state. If the camera is in auto mode, it will switch to manual mode, and vice versa. + /// + void CameraAutoModeToggle(); + + /// + /// Feedback that indicates whether the camera's auto mode is currently enabled. + /// + BoolFeedback CameraAutoModeIsOnFeedback { get; } + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraControls.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraControls.cs new file mode 100644 index 00000000..a4ed5937 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraControls.cs @@ -0,0 +1,13 @@ +using PepperDash.Core; + + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + + /// + /// Interface for devices that have camera controls + /// + public interface IHasCameraControls : IKeyName + { + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraFocusControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraFocusControl.cs new file mode 100644 index 00000000..bf266d56 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraFocusControl.cs @@ -0,0 +1,29 @@ + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Defines the contract for IHasCameraFocusControl + /// + public interface IHasCameraFocusControl : IHasCameraControls + { + /// + /// Focuses the camera near + /// + void FocusNear(); + + /// + /// Focuses the camera far + /// + void FocusFar(); + + /// + /// Stops the camera focus movement + /// + void FocusStop(); + + /// + /// Triggers the camera's auto focus functionality, if available. + /// + void TriggerAutoFocus(); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMute.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMute.cs new file mode 100644 index 00000000..cae6f5ef --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMute.cs @@ -0,0 +1,31 @@ +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Describes the ability to mute and unmute camera video + /// + public interface IHasCameraMute : IKeyName + { + /// + /// Feedback that indicates whether the camera is muted + /// + BoolFeedback CameraIsMutedFeedback { get; } + + /// + /// Mutes the camera video, preventing it from being sent to the far end + /// + void CameraMuteOn(); + + /// + /// Unmutes the camera video, allowing it to be sent to the far end + /// + void CameraMuteOff(); + + /// + /// Toggles the camera mute state. If the camera is muted, it will be unmuted, and vice versa. + /// + void CameraMuteToggle(); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMuteWithUnmuteRequest.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMuteWithUnmuteRequest.cs new file mode 100644 index 00000000..5426ea2b --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMuteWithUnmuteRequest.cs @@ -0,0 +1,16 @@ +using System; + + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Interface for devices that can mute and unmute their camera video, with an event for unmute requests + /// + public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute + { + /// + /// Event that is raised when a video unmute is requested, typically by the far end + /// + event EventHandler VideoUnmuteRequested; + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraOff.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraOff.cs new file mode 100644 index 00000000..6dc451c1 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraOff.cs @@ -0,0 +1,27 @@ +using PepperDash.Essentials.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + + + /// + /// To be implmented on codecs that can disable their camera(s) to blank the near end video + /// + public interface IHasCameraOff : IHasCameraControls + { + /// + /// Feedback that indicates whether the camera is off + /// + BoolFeedback CameraIsOffFeedback { get; } + + /// + /// Turns the camera off, blanking the near end video + /// + void CameraOff(); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPanControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPanControl.cs new file mode 100644 index 00000000..507dc555 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPanControl.cs @@ -0,0 +1,24 @@ + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Interface for camera pan control + /// + public interface IHasCameraPanControl : IHasCameraControls + { + /// + /// Pans the camera left + /// + void PanLeft(); + + /// + /// Pans the camera right + /// + void PanRight(); + + /// + /// Stops the camera pan movement + /// + void PanStop(); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPtzControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPtzControl.cs new file mode 100644 index 00000000..de2b52dd --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPtzControl.cs @@ -0,0 +1,14 @@ + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Defines the contract for IHasCameraPtzControl + /// + public interface IHasCameraPtzControl : IHasCameraPanControl, IHasCameraTiltControl, IHasCameraZoomControl + { + /// + /// Resets the camera position + /// + void PositionHome(); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraTiltControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraTiltControl.cs new file mode 100644 index 00000000..87dc1751 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraTiltControl.cs @@ -0,0 +1,24 @@ + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Defines the contract for IHasCameraTiltControl + /// + public interface IHasCameraTiltControl : IHasCameraControls + { + /// + /// Tilts the camera down + /// + void TiltDown(); + + /// + /// Tilts the camera up + /// + void TiltUp(); + + /// + /// Stops the camera tilt movement + /// + void TiltStop(); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraZoomControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraZoomControl.cs new file mode 100644 index 00000000..72bf16c4 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraZoomControl.cs @@ -0,0 +1,24 @@ + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Defines the contract for IHasCameraZoomControl + /// + public interface IHasCameraZoomControl : IHasCameraControls + { + /// + /// Zooms the camera in + /// + void ZoomIn(); + + /// + /// Zooms the camera out + /// + void ZoomOut(); + + /// + /// Stops the camera zoom movement + /// + void ZoomStop(); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameras.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameras.cs new file mode 100644 index 00000000..5a5962f8 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameras.cs @@ -0,0 +1,41 @@ +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using System; +using System.Collections.Generic; + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Interface for devices that have cameras + /// + [Obsolete("Use IHasCamerasWithControls instead. This interface will be removed in a future version")] + public interface IHasCameras : IKeyName + { + /// + /// Event that is raised when a camera is selected + /// + event EventHandler CameraSelected; + + /// + /// List of cameras on the device. This should be a list of CameraBase objects + /// + List Cameras { get; } + + /// + /// The currently selected camera. This should be a CameraBase object + /// + CameraBase SelectedCamera { get; } + + /// + /// Feedback that indicates the currently selected camera + /// + StringFeedback SelectedCameraFeedback { get; } + + /// + /// Selects a camera from the list of available cameras based on the provided key. + /// + /// The unique identifier or name of the camera to select. + void SelectCamera(string key); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCamerasWithControls.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCamerasWithControls.cs new file mode 100644 index 00000000..f7aff6d2 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCamerasWithControls.cs @@ -0,0 +1,40 @@ +using PepperDash.Core; +using PepperDash.Essentials.Core; +using System; +using System.Collections.Generic; + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Interface for devices that have cameras with controls + /// + public interface IHasCamerasWithControls : IKeyName, IKeyed + { + /// + /// List of cameras on the device. This should be a list of IHasCameraControls objects + /// + + List Cameras { get; } + + /// + /// The currently selected camera. This should be an IHasCameraControls object + /// + IHasCameraControls SelectedCamera { get; } + + /// + /// Feedback that indicates the currently selected camera + /// + StringFeedback SelectedCameraFeedback { get; } + + /// + /// Event that is raised when a camera is selected + /// + event EventHandler> CameraSelected; + + /// + /// Selects a camera from the list of available cameras based on the provided key. + /// + /// + void SelectCamera(string key); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCodecCameras.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCodecCameras.cs new file mode 100644 index 00000000..01cdf24e --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCodecCameras.cs @@ -0,0 +1,13 @@ + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + + /// + /// Defines the contract for IHasCodecCameras + /// + public interface IHasCodecCameras : IHasCameras, IHasFarEndCameraControl + { + + } + +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasFarEndCameraControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasFarEndCameraControl.cs new file mode 100644 index 00000000..10a4ba69 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasFarEndCameraControl.cs @@ -0,0 +1,23 @@ +using PepperDash.Core; +using PepperDash.Essentials.Core; + + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Interface for devices that have a far end camera control + /// + public interface IHasFarEndCameraControl : IKeyName + { + /// + /// Gets the far end camera, which is typically a CameraBase object that represents the camera at the far end of a call + /// + CameraBase FarEndCamera { get; } + + /// + /// Feedback that indicates whether the far end camera is being controlled + /// + BoolFeedback ControllingFarEndCameraFeedback { get; } + + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/eCameraControlMode.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/eCameraControlMode.cs new file mode 100644 index 00000000..c966ac41 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/eCameraControlMode.cs @@ -0,0 +1,24 @@ + + +namespace PepperDash.Essentials.Devices.Common.Cameras +{ + /// + /// Enum for camera control modes + /// + public enum eCameraControlMode + { + /// + /// Manual control mode, where the camera is controlled directly by the user or system + /// + Manual = 0, + /// + /// Off control mode, where the camera is turned off or disabled + /// + Off, + /// + /// Auto control mode, where the camera automatically adjusts settings based on the environment or conditions + /// + Auto + } + +} diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/Call.cs b/src/PepperDash.Essentials.Devices.Common/Codec/Call.cs new file mode 100644 index 00000000..807a29d0 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/Call.cs @@ -0,0 +1,26 @@ +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a Call + /// + public class Call + { + /// + /// Gets or sets the Number + /// + public string Number { get; set; } + /// + /// Gets or sets the Protocol + /// + public string Protocol { get; set; } + /// + /// Gets or sets the CallRate + /// + public string CallRate { get; set; } + /// + /// Gets or sets the CallType + /// + public string CallType { get; set; } + } + +} diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/IPresenterTrack.cs b/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/IPresenterTrack.cs index f3f164bd..134dc7b5 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/IPresenterTrack.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/IPresenterTrack.cs @@ -1,10 +1,5 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace PepperDash.Essentials.Devices.Common.Codec.Cisco { diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/ISpeakerTrack.cs b/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/ISpeakerTrack.cs index 83735183..522e6ad2 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/ISpeakerTrack.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/ISpeakerTrack.cs @@ -1,10 +1,5 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace PepperDash.Essentials.Devices.Common.Codec.Cisco { diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/CodecActiveCallItem.cs b/src/PepperDash.Essentials.Devices.Common/Codec/CodecActiveCallItem.cs index b0c91e4e..23a39f29 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/CodecActiveCallItem.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/CodecActiveCallItem.cs @@ -1,10 +1,6 @@  using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -17,55 +13,55 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public class CodecActiveCallItem { - [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] /// /// Gets or sets the Name /// + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] public string Name { get; set; } - [JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)] /// /// Gets or sets the Number /// + [JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)] public string Number { get; set; } - [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] - [JsonConverter(typeof(StringEnumConverter))] /// /// Gets or sets the Type /// + [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(StringEnumConverter))] public eCodecCallType Type { get; set; } - [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] - [JsonConverter(typeof(StringEnumConverter))] /// /// Gets or sets the Status /// + [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(StringEnumConverter))] public eCodecCallStatus Status { get; set; } - [JsonProperty("direction", NullValueHandling = NullValueHandling.Ignore)] - [JsonConverter(typeof(StringEnumConverter))] /// /// Gets or sets the Direction /// + [JsonProperty("direction", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(StringEnumConverter))] public eCodecCallDirection Direction { get; set; } - [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] /// /// Gets or sets the Id /// + [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] public string Id { get; set; } - [JsonProperty("isOnHold", NullValueHandling = NullValueHandling.Ignore)] /// /// Gets or sets the IsOnHold /// + [JsonProperty("isOnHold", NullValueHandling = NullValueHandling.Ignore)] public bool IsOnHold { get; set; } - [JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)] /// /// Gets or sets the Duration /// + [JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)] public TimeSpan Duration { get; set; } //public object CallMetaData { get; set; } @@ -81,7 +77,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec { return !(Status == eCodecCallStatus.Disconnected || Status == eCodecCallStatus.Disconnecting - || Status == eCodecCallStatus.Idle + || Status == eCodecCallStatus.Idle || Status == eCodecCallStatus.Unknown); } } @@ -97,6 +93,10 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public CodecActiveCallItem CallItem { get; private set; } + /// + /// Initializes a new instance of the CodecCallStatusItemChangeEventArgs class + /// + /// The call item that changed public CodecCallStatusItemChangeEventArgs(CodecActiveCallItem item) { CallItem = item; diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/CodecDirectory.cs b/src/PepperDash.Essentials.Devices.Common/Codec/CodecDirectory.cs new file mode 100644 index 00000000..df613941 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/CodecDirectory.cs @@ -0,0 +1,121 @@ + + +using System; +using System.Collections.Generic; +using System.Linq; + +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a codec directory + /// + public class CodecDirectory + { + /// + /// Represents the contents of the directory + /// We don't want to serialize this for messages to MobileControl. MC can combine Contacts and Folders to get the same data + /// + [JsonIgnore] + public List CurrentDirectoryResults { get; private set; } + + /// + /// Gets the Contacts in the CurrentDirectoryResults + /// + [JsonProperty("contacts")] + public List Contacts + { + get + { + return CurrentDirectoryResults.OfType().Cast().ToList(); + } + } + + /// + /// Gets the Folders in the CurrentDirectoryResults + /// + [JsonProperty("folders")] + public List Folders + { + get + { + return CurrentDirectoryResults.OfType().Cast().ToList(); + } + } + + /// + /// Used to store the ID of the current folder for CurrentDirectoryResults + /// Gets or sets the ResultsFolderId + /// + [JsonProperty("resultsFolderId")] + public string ResultsFolderId { get; set; } + + /// + /// Constructor for + /// + public CodecDirectory() + { + CurrentDirectoryResults = new List(); + } + + /// + /// Adds folders to the directory + /// + /// + public void AddFoldersToDirectory(List folders) + { + if (folders != null) + CurrentDirectoryResults.AddRange(folders); + + SortDirectory(); + } + + /// + /// Adds contacts to the directory + /// + /// + public void AddContactsToDirectory(List contacts) + { + if (contacts != null) + CurrentDirectoryResults.AddRange(contacts); + + SortDirectory(); + } + + /// + /// Filters the CurrentDirectoryResults by the predicate + /// + /// + + public void FilterContacts(Func predicate) + { + CurrentDirectoryResults = CurrentDirectoryResults.Where(predicate).ToList(); + } + + /// + /// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically + /// + private void SortDirectory() + { + var sortedFolders = new List(); + + sortedFolders.AddRange(CurrentDirectoryResults.Where(f => f is DirectoryFolder)); + + sortedFolders.OrderBy(f => f.Name); + + var sortedContacts = new List(); + + sortedContacts.AddRange(CurrentDirectoryResults.Where(c => c is DirectoryContact)); + + sortedFolders.OrderBy(c => c.Name); + + CurrentDirectoryResults.Clear(); + + CurrentDirectoryResults.AddRange(sortedFolders); + + CurrentDirectoryResults.AddRange(sortedContacts); + } + + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/CodecScheduleAwareness.cs b/src/PepperDash.Essentials.Devices.Common/Codec/CodecScheduleAwareness.cs new file mode 100644 index 00000000..4eea3d2a --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/CodecScheduleAwareness.cs @@ -0,0 +1,146 @@ + + +using System; +using System.Collections.Generic; +using Crestron.SimplSharp; +using PepperDash.Core; +using Serilog.Events; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a CodecScheduleAwareness + /// + public class CodecScheduleAwareness + { + List _meetings; + + /// + /// Event that is raised when a meeting event changes + /// + public event EventHandler MeetingEventChange; + + /// + /// Event that is raised when the meetings list has changed + /// + public event EventHandler MeetingsListHasChanged; + + private int _meetingWarningMinutes = 5; + + //private Meeting _previousChangedMeeting; + + //private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown; + + /// + /// Gets or sets the number of minutes before a meeting to issue a warning + /// + public int MeetingWarningMinutes + { + get { return _meetingWarningMinutes; } + set { _meetingWarningMinutes = value; } + } + + /// + /// Setter triggers MeetingsListHasChanged event + /// + public List Meetings + { + get + { + return _meetings; + } + set + { + _meetings = value; + MeetingsListHasChanged?.Invoke(this, new EventArgs()); + } + } + + private readonly CTimer _scheduleChecker; + + /// + /// Initializes a new instance of the CodecScheduleAwareness class with default poll time + /// + public CodecScheduleAwareness() + { + Meetings = new List(); + + _scheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000); + } + + /// + /// Initializes a new instance of the CodecScheduleAwareness class with specified poll time + /// + /// The poll time in milliseconds for checking schedule changes + public CodecScheduleAwareness(long pollTime) + { + Meetings = new List(); + + _scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime); + } + + /// + /// Helper method to fire MeetingEventChange. Should only fire once for each changeType on each meeting + /// + /// + /// + private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting) + { + Debug.LogMessage(LogEventLevel.Verbose, "*****************OnMeetingChange. id: {0} changeType: {1}**********************", meeting.Id, changeType); + if (changeType != (changeType & meeting.NotifiedChangeTypes)) + { + // Add this change type to the NotifiedChangeTypes + meeting.NotifiedChangeTypes |= changeType; + MeetingEventChange?.Invoke(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting }); + } + else + { + Debug.LogMessage(LogEventLevel.Verbose, "Meeting: {0} already notified of changeType: {1}", meeting.Id, changeType); + } + } + + + /// + /// Checks the schedule to see if any MeetingEventChange updates should be fired + /// + /// + private void CheckSchedule(object o) + { + // Iterate the meeting list and check if any meeting need to do anything + + const double meetingTimeEpsilon = 0.05; + foreach (var m in Meetings) + { + var changeType = eMeetingEventChangeType.Unknown; + + if (eMeetingEventChangeType.MeetingStartWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStartWarning) && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start + { + Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds); + changeType = eMeetingEventChangeType.MeetingStartWarning; + } + else if (eMeetingEventChangeType.MeetingStart != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStart) && Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start + { + Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStart"); + changeType = eMeetingEventChangeType.MeetingStart; + } + else if (eMeetingEventChangeType.MeetingEndWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEndWarning) && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end + { + Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEndWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingEnd.TotalMinutes, m.TimeToMeetingEnd.Seconds); + changeType = eMeetingEventChangeType.MeetingEndWarning; + } + else if (eMeetingEventChangeType.MeetingEnd != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEnd) && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended + { + Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEnd"); + changeType = eMeetingEventChangeType.MeetingEnd; + } + + if (changeType != eMeetingEventChangeType.Unknown) + { + OnMeetingChange(changeType, m); + } + } + + } + } + +} diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/ContactMethod.cs b/src/PepperDash.Essentials.Devices.Common/Codec/ContactMethod.cs new file mode 100644 index 00000000..9cbd43cb --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/ContactMethod.cs @@ -0,0 +1,37 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a ContactMethod + /// + public class ContactMethod + { + /// + /// Gets or sets the ContactMethodId + /// + [JsonProperty("contactMethodId")] + public string ContactMethodId { get; set; } + + /// + /// Gets or sets the Number + /// + [JsonProperty("number")] + public string Number { get; set; } + + /// + /// Gets or sets the Device + /// + [JsonProperty("device")] + [JsonConverter(typeof(StringEnumConverter))] + public eContactMethodDevice Device { get; set; } + + /// + /// Gets or sets the CallType + /// + [JsonProperty("callType")] + [JsonConverter(typeof(StringEnumConverter))] + public eContactMethodCallType CallType { get; set; } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryContact.cs b/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryContact.cs new file mode 100644 index 00000000..8fd8bf82 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryContact.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; + +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a DirectoryContact + /// + public class DirectoryContact : DirectoryItem + { + + /// + /// Gets or sets the ContactId + /// + [JsonProperty("contactId")] + public string ContactId { get; set; } + + /// + /// Gets or sets the Title + /// + [JsonProperty("title")] + public string Title { get; set; } + + /// + /// Gets or sets the ContactMethods + /// + [JsonProperty("contactMethods")] + public List ContactMethods { get; set; } + + /// + /// Constructor for + /// + public DirectoryContact() + { + ContactMethods = new List(); + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryEventArgs.cs b/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryEventArgs.cs new file mode 100644 index 00000000..f7ba8a5f --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryEventArgs.cs @@ -0,0 +1,21 @@ + + +using System; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a DirectoryEventArgs + /// + public class DirectoryEventArgs : EventArgs + { + /// + /// Gets or sets the Directory + /// + public CodecDirectory Directory { get; set; } + /// + /// Gets or sets the DirectoryIsOnRoot + /// + public bool DirectoryIsOnRoot { get; set; } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryFolder.cs b/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryFolder.cs new file mode 100644 index 00000000..6da08fba --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryFolder.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a DirectoryFolder + /// + public class DirectoryFolder : DirectoryItem + { + + /// + /// Gets or sets the Contacts + /// + [JsonProperty("contacts")] + public List Contacts { get; set; } + + /// + /// Constructor for + /// + public DirectoryFolder() + { + Contacts = new List(); + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryItem.cs b/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryItem.cs new file mode 100644 index 00000000..92996868 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/DirectoryItem.cs @@ -0,0 +1,41 @@ + + +using System; + +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a DirectoryItem + /// + public class DirectoryItem : ICloneable + { + /// + /// Clone method + /// + public object Clone() + { + return MemberwiseClone(); + } + + /// + /// Gets or sets the FolderId + /// + [JsonProperty("folderId")] + public string FolderId { get; set; } + + + /// + /// Gets or sets the Name + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// Gets or sets the ParentFolderId + /// + [JsonProperty("parentFolderId")] + public string ParentFolderId { get; set; } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/ICiscoCodecCameraConfig.cs b/src/PepperDash.Essentials.Devices.Common/Codec/ICiscoCodecCameraConfig.cs index fefb4b09..a93337aa 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/ICiscoCodecCameraConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/ICiscoCodecCameraConfig.cs @@ -1,31 +1,65 @@ -using Crestron.SimplSharpPro; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace PepperDash.Essentials.Devices.Common.Codec -{ +namespace PepperDash.Essentials.Devices.Common.Codec +{ /// /// Describes a cisco codec device that can allow configuration of cameras /// public interface ICiscoCodecCameraConfig { + /// + /// Sets the assigned serial number for the specified camera + /// + /// The camera identifier + /// The serial number to assign void SetCameraAssignedSerialNumber(uint cameraId, string serialNumber); + /// + /// Sets the name for the camera on the specified video connector + /// + /// The video connector identifier + /// The name to assign void SetCameraName(uint videoConnectorId, string name); + /// + /// Sets the input source type for the specified video connector + /// + /// The video connector identifier + /// The source type to set void SetInputSourceType(uint videoConnectorId, eCiscoCodecInputSourceType sourceType); } + /// + /// Enumeration of Cisco codec input source types + /// public enum eCiscoCodecInputSourceType { + /// + /// PC source type + /// PC, + + /// + /// Camera source type + /// camera, + + /// + /// Document camera source type + /// document_camera, + + /// + /// Media player source type + /// mediaplayer, + + /// + /// Other source type + /// other, + + /// + /// Whiteboard source type + /// whiteboard } } diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/IHasCallHold.cs b/src/PepperDash.Essentials.Devices.Common/Codec/IHasCallHold.cs index 8fbe2b9b..1445bd61 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/IHasCallHold.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/IHasCallHold.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec { /// /// Defines the contract for IHasCallHold diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/IHasDirectoryHistoryStack.cs b/src/PepperDash.Essentials.Devices.Common/Codec/IHasDirectoryHistoryStack.cs new file mode 100644 index 00000000..e46d8762 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/IHasDirectoryHistoryStack.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using PepperDash.Essentials.Devices.Common.Codec; + + +/// +/// Defines the contract for IHasDirectoryHistoryStack +/// +public interface IHasDirectoryHistoryStack : IHasDirectory +{ + /// + /// Gets the DirectoryBrowseHistoryStack + /// + Stack DirectoryBrowseHistoryStack { get; } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/IHasDoNotDisturb.cs b/src/PepperDash.Essentials.Devices.Common/Codec/IHasDoNotDisturb.cs index 7bb9b924..c989e671 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/IHasDoNotDisturb.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/IHasDoNotDisturb.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.Codec { @@ -34,6 +28,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec void ToggleDoNotDisturbMode(); } + /// + /// Defines the contract for devices that support Do Not Disturb mode with timeout functionality + /// public interface IHasDoNotDisturbModeWithTimeout : IHasDoNotDisturbMode { /// diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/IHasExternalSourceSwitching.cs b/src/PepperDash.Essentials.Devices.Common/Codec/IHasExternalSourceSwitching.cs index d22acbba..73884a2a 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/IHasExternalSourceSwitching.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/IHasExternalSourceSwitching.cs @@ -1,25 +1,54 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; namespace PepperDash.Essentials.Devices.Common.Codec { - /// - /// Defines the contract for IHasExternalSourceSwitching - /// + /// + /// Defines the contract for IHasExternalSourceSwitching + /// public interface IHasExternalSourceSwitching { + /// + /// Gets a value indicating whether the external source list is enabled + /// bool ExternalSourceListEnabled { get; } - string ExternalSourceInputPort { get; } + + /// + /// Gets the external source input port identifier + /// + string ExternalSourceInputPort { get; } + + /// + /// Adds an external source to the available sources + /// + /// The connector identifier + /// The unique key for the source + /// The display name for the source + /// The type of external source void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type); + + /// + /// Sets the state of the specified external source + /// + /// The unique key of the external source + /// The mode to set for the source void SetExternalSourceState(string key, eExternalSourceMode mode); + + /// + /// Clears all external sources from the list + /// void ClearExternalSources(); - void SetSelectedSource(string key); - Action RunRouteAction { set;} + + /// + /// Sets the selected source by its key + /// + /// The unique key of the source to select + void SetSelectedSource(string key); + + /// + /// Sets the action to run when routing between sources + /// + Action RunRouteAction { set; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/IInvitableContact.cs b/src/PepperDash.Essentials.Devices.Common/Codec/IInvitableContact.cs new file mode 100644 index 00000000..598a9b22 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/IInvitableContact.cs @@ -0,0 +1,13 @@ +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Defines the contract for IInvitableContact + /// + public interface IInvitableContact + { + /// + /// Gets a value indicating whether this contact is invitable + /// + bool IsInvitableContact { get; } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/InvitableDirectoryContact.cs b/src/PepperDash.Essentials.Devices.Common/Codec/InvitableDirectoryContact.cs new file mode 100644 index 00000000..68707c35 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/InvitableDirectoryContact.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents an InvitableDirectoryContact + /// + public class InvitableDirectoryContact : DirectoryContact, IInvitableContact + { + /// + /// Gets a value indicating whether this contact is invitable + /// + [JsonProperty("isInvitableContact")] + public bool IsInvitableContact + { + get + { + return this is IInvitableContact; + } + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/Meeting.cs b/src/PepperDash.Essentials.Devices.Common/Codec/Meeting.cs new file mode 100644 index 00000000..22bc697a --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/Meeting.cs @@ -0,0 +1,182 @@ + + +using System; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a Meeting + /// + public class Meeting + { + /// + /// Minutes before the meeting to show warning + /// + [JsonProperty("minutesBeforeMeeting")] + public int MinutesBeforeMeeting; + + /// + /// Gets or sets the meeting ID + /// + [JsonProperty("id")] + public string Id { get; set; } + /// + /// Gets or sets the meeting organizer + /// + [JsonProperty("organizer")] + public string Organizer { get; set; } + /// + /// Gets or sets the Title + /// + [JsonProperty("title")] + public string Title { get; set; } + /// + /// Gets or sets the Agenda + /// + [JsonProperty("agenda")] + public string Agenda { get; set; } + + /// + /// Gets the meeting warning time span in minutes before the meeting starts + /// + [JsonProperty("meetingWarningMinutes")] + public TimeSpan MeetingWarningMinutes + { + get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); } + } + /// + /// Gets the time remaining until the meeting starts + /// + [JsonProperty("timeToMeetingStart")] + public TimeSpan TimeToMeetingStart + { + get + { + return StartTime - DateTime.Now; + } + } + /// + /// Gets the time remaining until the meeting ends + /// + [JsonProperty("timeToMeetingEnd")] + public TimeSpan TimeToMeetingEnd + { + get + { + return EndTime - DateTime.Now; + } + } + /// + /// Gets or sets the StartTime + /// + [JsonProperty("startTime")] + public DateTime StartTime { get; set; } + /// + /// Gets or sets the EndTime + /// + [JsonProperty("endTime")] + public DateTime EndTime { get; set; } + /// + /// Gets the duration of the meeting + /// + [JsonProperty("duration")] + public TimeSpan Duration + { + get + { + return EndTime - StartTime; + } + } + /// + /// Gets or sets the Privacy + /// + [JsonProperty("privacy")] + public eMeetingPrivacy Privacy { get; set; } + /// + /// Gets a value indicating whether the meeting can be joined + /// + [JsonProperty("joinable")] + public bool Joinable + { + get + { + var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now + && DateTime.Now <= EndTime.AddSeconds(-_joinableCooldownSeconds); + //Debug.LogMessage(LogEventLevel.Verbose, "Meeting Id: {0} joinable: {1}", Id, joinable); + return joinable; + } + } + + /// + /// Gets or sets the Dialable + /// + [JsonProperty("dialable")] + public bool Dialable { get; set; } + + //public string ConferenceNumberToDial { get; set; } + + /// + /// Gets or sets the ConferencePassword + /// + [JsonProperty("conferencePassword")] + public string ConferencePassword { get; set; } + + /// + /// Gets or sets the IsOneButtonToPushMeeting + /// + [JsonProperty("isOneButtonToPushMeeting")] + public bool IsOneButtonToPushMeeting { get; set; } + + /// + /// Gets or sets the Calls + /// + [JsonProperty("calls")] + public List Calls { get; private set; } + + /// + /// Tracks the change types that have already been notified for + /// Gets or sets the NotifiedChangeTypes + /// + [JsonIgnore] + public eMeetingEventChangeType NotifiedChangeTypes { get; set; } + + [JsonIgnore] private readonly int _joinableCooldownSeconds; + + /// + /// Constructor for Meeting + /// + public Meeting() + { + Calls = new List(); + _joinableCooldownSeconds = 300; + } + + /// + /// Constructor for Meeting + /// + /// Number of seconds after meeting start when it is no longer joinable + public Meeting(int joinableCooldownSeconds) + { + Calls = new List(); + _joinableCooldownSeconds = joinableCooldownSeconds; + } + + + + #region Overrides of Object + + /// + /// ToString method + /// + /// + public override string ToString() + { + return string.Format("{0}:{1}: {2}-{3}", Title, Agenda, StartTime, EndTime); + } + + #endregion + } + +} diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/MeetingEventArgs.cs b/src/PepperDash.Essentials.Devices.Common/Codec/MeetingEventArgs.cs new file mode 100644 index 00000000..ed706a1c --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/MeetingEventArgs.cs @@ -0,0 +1,22 @@ + + +using System; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Represents a MeetingEventArgs + /// + public class MeetingEventArgs : EventArgs + { + /// + /// Gets or sets the ChangeType + /// + public eMeetingEventChangeType ChangeType { get; set; } + /// + /// Gets or sets the Meeting + /// + public Meeting Meeting { get; set; } + } + +} diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallDirection.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallDirection.cs index 01eca3d1..e10f61a3 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallDirection.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallDirection.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec { /// @@ -12,7 +6,20 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public enum eCodecCallDirection { - Unknown = 0, Incoming, Outgoing + /// + /// Unknown call direction + /// + Unknown = 0, + + /// + /// Incoming call direction + /// + Incoming, + + /// + /// Outgoing call direction + /// + Outgoing } /// diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallStatus.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallStatus.cs index b2ab5d99..6116ab16 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallStatus.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallStatus.cs @@ -1,27 +1,68 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec { /// /// Enumeration of eCodecCallStatus values /// public enum eCodecCallStatus { + /// + /// Unknown call status + /// Unknown = 0, - Connected, - Connecting, - Dialing, + + /// + /// Call is connected + /// + Connected, + + /// + /// Call is connecting + /// + Connecting, + + /// + /// Call is dialing + /// + Dialing, + + /// + /// Call is disconnected + /// Disconnected, - Disconnecting, - EarlyMedia, + + /// + /// Call is disconnecting + /// + Disconnecting, + + /// + /// Early media is being sent/received + /// + EarlyMedia, + + /// + /// Call is idle + /// Idle, - OnHold, - Ringing, - Preserved, + + /// + /// Call is on hold + /// + OnHold, + + /// + /// Call is ringing + /// + Ringing, + + /// + /// Call is preserved + /// + Preserved, + + /// + /// Call is remote preserved + /// RemotePreserved, } diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallType.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallType.cs index cf15140e..2b9609fb 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallType.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallType.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec { /// @@ -12,10 +6,29 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public enum eCodecCallType { - Unknown = 0, - Audio, - Video, - AudioCanEscalate, + /// + /// Unknown call type + /// + Unknown = 0, + + /// + /// Audio-only call type + /// + Audio, + + /// + /// Video call type + /// + Video, + + /// + /// Audio call that can be escalated to video + /// + AudioCanEscalate, + + /// + /// Forward all call type + /// ForwardAllCall } diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eContactMethodCallType.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eContactMethodCallType.cs new file mode 100644 index 00000000..8e46a721 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eContactMethodCallType.cs @@ -0,0 +1,21 @@ +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Enumeration of eContactMethodCallType values + /// + public enum eContactMethodCallType + { + /// + /// Unknown call type + /// + Unknown = 0, + /// + /// Audio call type + /// + Audio, + /// + /// Video call type + /// + Video + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eContactMethodDevice.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eContactMethodDevice.cs new file mode 100644 index 00000000..83bfc995 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eContactMethodDevice.cs @@ -0,0 +1,29 @@ +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Enumeration of eContactMethodDevice values + /// + public enum eContactMethodDevice + { + /// + /// Unknown contact method + /// + Unknown = 0, + /// + /// Mobile contact method + /// + Mobile, + /// + /// Other contact method + /// + Other, + /// + /// Telephone contact method + /// + Telephone, + /// + /// Video contact method + /// + Video + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingEventChangeType.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingEventChangeType.cs new file mode 100644 index 00000000..2861703f --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingEventChangeType.cs @@ -0,0 +1,35 @@ + + +using System; + +namespace PepperDash.Essentials.Devices.Common.Codec +{ + /// + /// Enumeration of eMeetingEventChangeType values + /// + [Flags] + public enum eMeetingEventChangeType + { + /// + /// Unknown change type + /// + Unknown = 0, + /// + /// Meeting start warning + /// + MeetingStartWarning = 1, + /// + /// Meeting start + /// + MeetingStart = 2, + /// + /// Meeting end warning + /// + MeetingEndWarning = 4, + /// + /// Meeting end + /// + MeetingEnd = 8 + } + +} diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingPrivacy.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingPrivacy.cs index 29ac5247..19a6d31b 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingPrivacy.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingPrivacy.cs @@ -1,18 +1,23 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec { /// /// Enumeration of eMeetingPrivacy values /// public enum eMeetingPrivacy { + /// + /// Unknown meeting privacy level + /// Unknown = 0, + + /// + /// Public meeting + /// Public, + + /// + /// Private meeting + /// Private } diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iCodecAudio.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iCodecAudio.cs index d61f7d26..eeab2801 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iCodecAudio.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iCodecAudio.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.Codec { diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallFavorites.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallFavorites.cs index ae5351c1..eeb6610f 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallFavorites.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallFavorites.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; +using System.Collections.Generic; namespace PepperDash.Essentials.Devices.Common.Codec { @@ -11,6 +7,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public interface IHasCallFavorites { + /// + /// Gets the call favorites for this device + /// CodecCallFavorites CallFavorites { get; } } @@ -24,6 +23,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public List Favorites { get; set; } + /// + /// Initializes a new instance of the CodecCallFavorites class + /// public CodecCallFavorites() { Favorites = new List(); diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallHistory.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallHistory.cs index cd7d7b96..7f495daa 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallHistory.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallHistory.cs @@ -2,10 +2,9 @@ using System; using System.Collections.Generic; -using PepperDash.Essentials.Devices.Common.VideoCodec; - using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Devices.Common.Codec { @@ -15,8 +14,15 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public interface IHasCallHistory { + /// + /// Gets the call history for this device + /// CodecCallHistory CallHistory { get; } + /// + /// Removes the specified call history entry + /// + /// The call history entry to remove void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry); } @@ -25,9 +31,24 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public enum eCodecOccurrenceType { + /// + /// Unknown occurrence type + /// Unknown = 0, + + /// + /// Call was placed (outgoing) + /// Placed = 1, + + /// + /// Call was received (incoming) + /// Received = 2, + + /// + /// Call received no answer + /// NoAnswer = 3, } @@ -36,6 +57,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public class CodecCallHistory { + /// + /// Event that is raised when the recent calls list has changed + /// public event EventHandler RecentCallsListHasChanged; /// @@ -48,6 +72,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// CallHistoryEntry ListEmptyEntry; + /// + /// Initializes a new instance of the CodecCallHistory class + /// public CodecCallHistory() { ListEmptyEntry = new CallHistoryEntry() { Name = "No Recent Calls" }; @@ -80,15 +107,22 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public class CallHistoryEntry : CodecActiveCallItem { - [JsonConverter(typeof(IsoDateTimeConverter))] - [JsonProperty("startTime")] /// /// Gets or sets the StartTime /// + [JsonConverter(typeof(IsoDateTimeConverter))] + [JsonProperty("startTime")] public DateTime StartTime { get; set; } + /// + /// Gets or sets the occurrence type for this call history entry + /// [JsonConverter(typeof(StringEnumConverter))] [JsonProperty("occurrenceType")] public eCodecOccurrenceType OccurrenceType { get; set; } + + /// + /// Gets or sets the occurrence history identifier + /// [JsonProperty("occurrenceHistoryId")] public string OccurrenceHistoryId { get; set; } } @@ -119,7 +153,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec } // Check if list is empty and if so, add an item to display No Recent Calls - if(genericEntries.Count == 0) + if (genericEntries.Count == 0) genericEntries.Add(ListEmptyEntry); RecentCalls = genericEntries; diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasContentSharing.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasContentSharing.cs index e944b432..2dea5b4a 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasContentSharing.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasContentSharing.cs @@ -1,11 +1,4 @@ -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; namespace PepperDash.Essentials.Devices.Common.Codec @@ -15,12 +8,29 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public interface IHasContentSharing { + /// + /// Gets feedback indicating whether content sharing is currently active + /// BoolFeedback SharingContentIsOnFeedback { get; } + + /// + /// Gets feedback about the current sharing source + /// StringFeedback SharingSourceFeedback { get; } + /// + /// Gets a value indicating whether content should be automatically shared while in a call + /// bool AutoShareContentWhileInCall { get; } + /// + /// Starts content sharing + /// void StartSharing(); + + /// + /// Stops content sharing + /// void StopSharing(); } diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasDialer.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasDialer.cs index bce2dee3..a5373004 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasDialer.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasDialer.cs @@ -1,10 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.Codec { @@ -15,15 +9,49 @@ namespace PepperDash.Essentials.Devices.Common.Codec { // Add requirements for Dialer functionality + /// + /// Event that is raised when call status changes + /// event EventHandler CallStatusChange; + /// + /// Dials the specified number + /// + /// The number to dial void Dial(string number); + + /// + /// Ends the specified active call + /// + /// The active call to end void EndCall(CodecActiveCallItem activeCall); + + /// + /// Ends all active calls + /// void EndAllCalls(); + + /// + /// Accepts the specified incoming call + /// + /// The call item to accept void AcceptCall(CodecActiveCallItem item); + + /// + /// Rejects the specified incoming call + /// + /// The call item to reject void RejectCall(CodecActiveCallItem item); + + /// + /// Sends DTMF digits during a call + /// + /// The DTMF digit(s) to send void SendDtmf(string digit); + /// + /// Gets a value indicating whether the device is currently in a call + /// bool IsInCall { get; } } diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasDirectory.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasDirectory.cs index de82bcfb..83cc6c8d 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasDirectory.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasDirectory.cs @@ -1,319 +1,59 @@  using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - - -using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Devices.Common.Codec { - /// - /// Defines the API for codecs with a directory - /// + /// + /// Defines the API for codecs with a directory + /// public interface IHasDirectory { + /// + /// Event that fires when a directory result is returned from the codec + /// event EventHandler DirectoryResultReturned; + /// + /// Gets the DirectoryRoot + /// CodecDirectory DirectoryRoot { get; } + /// + /// Gets the CurrentDirectoryResult + /// CodecDirectory CurrentDirectoryResult { get; } + /// + /// Gets the PhonebookSyncState + /// CodecPhonebookSyncState PhonebookSyncState { get; } + /// + /// Method to initiate a search of the directory on the server + /// void SearchDirectory(string searchString); + /// + /// Method to get the contents of a specific folder in the directory on the server + /// void GetDirectoryFolderContents(string folderId); + /// + /// Method to set the current directory to the root folder + /// void SetCurrentDirectoryToRoot(); + /// + /// Method to get the contents of the parent folder in the directory on the server + /// void GetDirectoryParentFolderContents(); + /// + /// Gets the CurrentDirectoryResultIsNotDirectoryRoot + /// BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; } } - - /// - /// Defines the contract for IHasDirectoryHistoryStack - /// - public interface IHasDirectoryHistoryStack : IHasDirectory - { - Stack DirectoryBrowseHistoryStack { get; } - } - - - /// - /// Represents a DirectoryEventArgs - /// - public class DirectoryEventArgs : EventArgs - { - /// - /// Gets or sets the Directory - /// - public CodecDirectory Directory { get; set; } - /// - /// Gets or sets the DirectoryIsOnRoot - /// - public bool DirectoryIsOnRoot { get; set; } - } - - /// - /// Represents a codec directory - /// - public class CodecDirectory - { - /// - /// Represents the contents of the directory - /// We don't want to serialize this for messages to MobileControl. MC can combine Contacts and Folders to get the same data - /// - [JsonIgnore] - public List CurrentDirectoryResults { get; private set; } - - [JsonProperty("contacts")] - public List Contacts - { - get - { - return CurrentDirectoryResults.OfType().Cast().ToList(); - } - } - - [JsonProperty("folders")] - public List Folders - { - get - { - return CurrentDirectoryResults.OfType().Cast().ToList(); - } - } - - /// - /// Used to store the ID of the current folder for CurrentDirectoryResults - /// - [JsonProperty("resultsFolderId")] - /// - /// Gets or sets the ResultsFolderId - /// - public string ResultsFolderId { get; set; } - - public CodecDirectory() - { - CurrentDirectoryResults = new List(); - } - - /// - /// Adds folders to the directory - /// - /// - /// - /// AddFoldersToDirectory method - /// - public void AddFoldersToDirectory(List folders) - { - if(folders != null) - CurrentDirectoryResults.AddRange(folders); - - SortDirectory(); - } - - /// - /// Adds contacts to the directory - /// - /// - /// - /// AddContactsToDirectory method - /// - public void AddContactsToDirectory(List contacts) - { - if(contacts != null) - CurrentDirectoryResults.AddRange(contacts); - - SortDirectory(); - } - - /// - /// Filters the CurrentDirectoryResults by the predicate - /// - /// - /// - /// FilterContacts method - /// - public void FilterContacts(Func predicate) - { - CurrentDirectoryResults = CurrentDirectoryResults.Where(predicate).ToList(); - } - - /// - /// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically - /// - private void SortDirectory() - { - var sortedFolders = new List(); - - sortedFolders.AddRange(CurrentDirectoryResults.Where(f => f is DirectoryFolder)); - - sortedFolders.OrderBy(f => f.Name); - - var sortedContacts = new List(); - - sortedContacts.AddRange(CurrentDirectoryResults.Where(c => c is DirectoryContact)); - - sortedFolders.OrderBy(c => c.Name); - - CurrentDirectoryResults.Clear(); - - CurrentDirectoryResults.AddRange(sortedFolders); - - CurrentDirectoryResults.AddRange(sortedContacts); - } - - } - - /// - /// Defines the contract for IInvitableContact - /// - public interface IInvitableContact - { - bool IsInvitableContact { get; } - } - - public class InvitableDirectoryContact : DirectoryContact, IInvitableContact - { - [JsonProperty("isInvitableContact")] - public bool IsInvitableContact - { - get - { - return this is IInvitableContact; - } - } - } - - /// - /// Represents a DirectoryItem - /// - public class DirectoryItem : ICloneable - { - /// - /// Clone method - /// - public object Clone() - { - return this.MemberwiseClone(); - } - - [JsonProperty("folderId")] - public string FolderId { get; set; } - - [JsonProperty("name")] - /// - /// Gets or sets the Name - /// - public string Name { get; set; } - - [JsonProperty("parentFolderId")] - /// - /// Gets or sets the ParentFolderId - /// - public string ParentFolderId { get; set; } - } - - /// - /// Represents a DirectoryFolder - /// - public class DirectoryFolder : DirectoryItem - { - [JsonProperty("contacts")] - /// - /// Gets or sets the Contacts - /// - public List Contacts { get; set; } - - - public DirectoryFolder() - { - Contacts = new List(); - } - } - - /// - /// Represents a DirectoryContact - /// - public class DirectoryContact : DirectoryItem - { - [JsonProperty("contactId")] - /// - /// Gets or sets the ContactId - /// - public string ContactId { get; set; } - - [JsonProperty("title")] - public string Title { get; set; } - - [JsonProperty("contactMethods")] - public List ContactMethods { get; set; } - - public DirectoryContact() - { - ContactMethods = new List(); - } - } - - /// - /// Represents a ContactMethod - /// - public class ContactMethod - { - [JsonProperty("contactMethodId")] - /// - /// Gets or sets the ContactMethodId - /// - public string ContactMethodId { get; set; } - - [JsonProperty("number")] - public string Number { get; set; } - - [JsonProperty("device")] - [JsonConverter(typeof(StringEnumConverter))] - /// - /// Gets or sets the Device - /// - public eContactMethodDevice Device { get; set; } - - [JsonProperty("callType")] - [JsonConverter(typeof(StringEnumConverter))] - /// - /// Gets or sets the CallType - /// - public eContactMethodCallType CallType { get; set; } - } - - /// - /// Enumeration of eContactMethodDevice values - /// - public enum eContactMethodDevice - { - Unknown = 0, - Mobile, - Other, - Telephone, - Video - } - - /// - /// Enumeration of eContactMethodCallType values - /// - public enum eContactMethodCallType - { - Unknown = 0, - Audio, - Video - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs index 240ac15f..ed17762a 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs @@ -1,339 +1,20 @@ - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Core; - -using Newtonsoft.Json; -using Serilog.Events; - -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec { - [Flags] - /// - /// Enumeration of eMeetingEventChangeType values - /// - public enum eMeetingEventChangeType - { - Unknown = 0, - MeetingStartWarning = 1, - MeetingStart = 2, - MeetingEndWarning = 4, - MeetingEnd = 8 - } /// /// Defines the contract for IHasScheduleAwareness /// public interface IHasScheduleAwareness { + /// + /// Gets the CodecScheduleAwareness instance + /// CodecScheduleAwareness CodecSchedule { get; } + /// + /// Method to initiate getting the schedule from the server + /// void GetSchedule(); } - /// - /// Represents a CodecScheduleAwareness - /// - public class CodecScheduleAwareness - { - List _meetings; - - public event EventHandler MeetingEventChange; - - public event EventHandler MeetingsListHasChanged; - - private int _meetingWarningMinutes = 5; - - //private Meeting _previousChangedMeeting; - - //private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown; - - public int MeetingWarningMinutes - { - get { return _meetingWarningMinutes; } - set { _meetingWarningMinutes = value; } - } - - /// - /// Setter triggers MeetingsListHasChanged event - /// - public List Meetings - { - get - { - return _meetings; - } - set - { - _meetings = value; - MeetingsListHasChanged?.Invoke(this, new EventArgs()); - } - } - - private readonly CTimer _scheduleChecker; - - public CodecScheduleAwareness() - { - Meetings = new List(); - - _scheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000); - } - - public CodecScheduleAwareness(long pollTime) - { - Meetings = new List(); - - _scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime); - } - - /// - /// Helper method to fire MeetingEventChange. Should only fire once for each changeType on each meeting - /// - /// - /// - private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting) - { - Debug.LogMessage(LogEventLevel.Verbose, "*****************OnMeetingChange. id: {0} changeType: {1}**********************", meeting.Id, changeType); - if (changeType != (changeType & meeting.NotifiedChangeTypes)) - { - // Add this change type to the NotifiedChangeTypes - meeting.NotifiedChangeTypes |= changeType; - MeetingEventChange?.Invoke(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting }); - } - else - { - Debug.LogMessage(LogEventLevel.Verbose, "Meeting: {0} already notified of changeType: {1}", meeting.Id, changeType); - } - } - - - /// - /// Checks the schedule to see if any MeetingEventChange updates should be fired - /// - /// - private void CheckSchedule(object o) - { - // Iterate the meeting list and check if any meeting need to do anything - - const double meetingTimeEpsilon = 0.05; - foreach (var m in Meetings) - { - var changeType = eMeetingEventChangeType.Unknown; - - if (eMeetingEventChangeType.MeetingStartWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStartWarning) && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start - { - Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds); - changeType = eMeetingEventChangeType.MeetingStartWarning; - } - else if (eMeetingEventChangeType.MeetingStart != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStart) && Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start - { - Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStart"); - changeType = eMeetingEventChangeType.MeetingStart; - } - else if (eMeetingEventChangeType.MeetingEndWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEndWarning) && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end - { - Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEndWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingEnd.TotalMinutes, m.TimeToMeetingEnd.Seconds); - changeType = eMeetingEventChangeType.MeetingEndWarning; - } - else if (eMeetingEventChangeType.MeetingEnd != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEnd) && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended - { - Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEnd"); - changeType = eMeetingEventChangeType.MeetingEnd; - } - - if (changeType != eMeetingEventChangeType.Unknown) - { - OnMeetingChange(changeType, m); - } - } - - } - } - - /// - /// Represents a Meeting - /// - public class Meeting - { - [JsonProperty("minutesBeforeMeeting")] - public int MinutesBeforeMeeting; - - [JsonProperty("id")] - public string Id { get; set; } - [JsonProperty("organizer")] - public string Organizer { get; set; } - [JsonProperty("title")] - /// - /// Gets or sets the Title - /// - public string Title { get; set; } - [JsonProperty("agenda")] - /// - /// Gets or sets the Agenda - /// - public string Agenda { get; set; } - - [JsonProperty("meetingWarningMinutes")] - public TimeSpan MeetingWarningMinutes - { - get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); } - } - [JsonProperty("timeToMeetingStart")] - public TimeSpan TimeToMeetingStart - { - get - { - return StartTime - DateTime.Now; - } - } - [JsonProperty("timeToMeetingEnd")] - public TimeSpan TimeToMeetingEnd - { - get - { - return EndTime - DateTime.Now; - } - } - [JsonProperty("startTime")] - /// - /// Gets or sets the StartTime - /// - public DateTime StartTime { get; set; } - [JsonProperty("endTime")] - /// - /// Gets or sets the EndTime - /// - public DateTime EndTime { get; set; } - [JsonProperty("duration")] - public TimeSpan Duration - { - get - { - return EndTime - StartTime; - } - } - [JsonProperty("privacy")] - /// - /// Gets or sets the Privacy - /// - public eMeetingPrivacy Privacy { get; set; } - [JsonProperty("joinable")] - public bool Joinable - { - get - { - var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now - && DateTime.Now <= EndTime.AddSeconds(-_joinableCooldownSeconds); - //Debug.LogMessage(LogEventLevel.Verbose, "Meeting Id: {0} joinable: {1}", Id, joinable); - return joinable; - } - } - - [JsonProperty("dialable")] - /// - /// Gets or sets the Dialable - /// - public bool Dialable { get; set; } - - //public string ConferenceNumberToDial { get; set; } - [JsonProperty("conferencePassword")] - /// - /// Gets or sets the ConferencePassword - /// - public string ConferencePassword { get; set; } - [JsonProperty("isOneButtonToPushMeeting")] - /// - /// Gets or sets the IsOneButtonToPushMeeting - /// - public bool IsOneButtonToPushMeeting { get; set; } - - [JsonProperty("calls")] - /// - /// Gets or sets the Calls - /// - public List Calls { get; private set; } - - /// - /// Tracks the change types that have already been notified for - /// - [JsonIgnore] - /// - /// Gets or sets the NotifiedChangeTypes - /// - public eMeetingEventChangeType NotifiedChangeTypes { get; set; } - - [JsonIgnore] private readonly int _joinableCooldownSeconds; - - - public Meeting() - { - Calls = new List(); - _joinableCooldownSeconds = 300; - } - - public Meeting(int joinableCooldownSeconds) - { - Calls = new List(); - _joinableCooldownSeconds = joinableCooldownSeconds; - } - - - - #region Overrides of Object - - /// - /// ToString method - /// - /// - public override string ToString() - { - return String.Format("{0}:{1}: {2}-{3}", Title, Agenda, StartTime, EndTime); - } - - #endregion - } - - /// - /// Represents a Call - /// - public class Call - { - /// - /// Gets or sets the Number - /// - public string Number { get; set; } - /// - /// Gets or sets the Protocol - /// - public string Protocol { get; set; } - /// - /// Gets or sets the CallRate - /// - public string CallRate { get; set; } - /// - /// Gets or sets the CallType - /// - public string CallType { get; set; } - } - - /// - /// Represents a MeetingEventArgs - /// - public class MeetingEventArgs : EventArgs - { - /// - /// Gets or sets the ChangeType - /// - public eMeetingEventChangeType ChangeType { get; set; } - /// - /// Gets or sets the Meeting - /// - public Meeting Meeting { get; set; } - } - } diff --git a/src/PepperDash.Essentials.Devices.Common/DSP/DspBase.cs b/src/PepperDash.Essentials.Devices.Common/DSP/DspBase.cs index 296eb91a..e20abc9c 100644 --- a/src/PepperDash.Essentials.Devices.Common/DSP/DspBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/DSP/DspBase.cs @@ -1,61 +1,84 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.DeviceTypeInterfaces; namespace PepperDash.Essentials.Devices.Common.DSP { - public abstract class DspBase : EssentialsDevice, ILevelControls - { - public Dictionary LevelControlPoints { get; private set; } + /// + /// Base class for DSP devices + /// + public abstract class DspBase : EssentialsDevice, ILevelControls + { + /// + /// Gets the collection of level control points + /// + public Dictionary LevelControlPoints { get; private set; } + /// + /// Gets the collection of dialer control points + /// public Dictionary DialerControlPoints { get; private set; } + /// + /// Gets the collection of switcher control points + /// public Dictionary SwitcherControlPoints { get; private set; } - public DspBase(string key, string name) : - base(key, name) - { + /// + /// Initializes a new instance of the DspBase class + /// + /// The device key + /// The device name + public DspBase(string key, string name) : + base(key, name) + { - LevelControlPoints = new Dictionary(); - DialerControlPoints = new Dictionary(); - SwitcherControlPoints = new Dictionary(); - } + LevelControlPoints = new Dictionary(); + DialerControlPoints = new Dictionary(); + SwitcherControlPoints = new Dictionary(); + } - // in audio call feedback + // in audio call feedback - // VOIP - // Phone dialer + // VOIP + // Phone dialer - } + } - // Fusion - // Privacy state - // Online state - // level/mutes ? - - // AC Log call stats - - // Typical presets: - // call default preset to restore levels and mutes + // Fusion + // Privacy state + // Online state + // level/mutes ? - public abstract class DspControlPoint :IKeyed - { + // AC Log call stats + + // Typical presets: + // call default preset to restore levels and mutes + + /// + /// Base class for DSP control points + /// + public abstract class DspControlPoint : IKeyed + { /// /// Gets or sets the Key /// public string Key { get; } + /// + /// Initializes a new instance of the DspControlPoint class + /// + /// The control point key protected DspControlPoint(string key) => Key = key; - } + } - public abstract class DspLevelControlPoint :DspControlPoint, IBasicVolumeWithFeedback + /// + /// Base class for DSP level control points with volume and mute functionality + /// + public abstract class DspLevelControlPoint : DspControlPoint, IBasicVolumeWithFeedback { /// /// Gets or sets the MuteFeedback @@ -66,30 +89,63 @@ namespace PepperDash.Essentials.Devices.Common.DSP /// public IntFeedback VolumeLevelFeedback { get; } + /// + /// Initializes a new instance of the DspLevelControlPoint class + /// + /// The control point key + /// Function to get mute status + /// Function to get volume level protected DspLevelControlPoint(string key, Func muteFeedbackFunc, Func volumeLevelFeedbackFunc) : base(key) { - MuteFeedback = new BoolFeedback(muteFeedbackFunc); - VolumeLevelFeedback = new IntFeedback(volumeLevelFeedbackFunc); + MuteFeedback = new BoolFeedback("mute", muteFeedbackFunc); + VolumeLevelFeedback = new IntFeedback("volume", volumeLevelFeedbackFunc); } + /// + /// Turns mute off + /// public abstract void MuteOff(); + /// + /// Turns mute on + /// public abstract void MuteOn(); + /// + /// Toggles mute state + /// public abstract void MuteToggle(); + /// + /// Sets the volume level + /// + /// The volume level to set public abstract void SetVolume(ushort level); + /// + /// Decreases volume + /// + /// True when pressed, false when released public abstract void VolumeDown(bool pressRelease); + /// + /// Increases volume + /// + /// True when pressed, false when released public abstract void VolumeUp(bool pressRelease); } - - public abstract class DspDialerBase:DspControlPoint - { + /// + /// Base class for DSP dialer control points + /// + public abstract class DspDialerBase : DspControlPoint + { + /// + /// Initializes a new instance of the DspDialerBase class + /// + /// The dialer control point key protected DspDialerBase(string key) : base(key) { } - } + } - // Main program - // VTC - // ATC - // Mics, unusual + // Main program + // VTC + // ATC + // Mics, unusual } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs b/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs index 178c53a7..2c7507ba 100644 --- a/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs +++ b/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs @@ -14,7 +14,9 @@ namespace PepperDash.Essentials.Devices.Common /// public class DeviceFactory { - + /// + /// Initializes a new instance of the DeviceFactory class + /// public DeviceFactory() { var assy = Assembly.GetExecutingAssembly(); diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/BasicIrDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/BasicIrDisplay.cs index 52fc5233..858cdf42 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/BasicIrDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/BasicIrDisplay.cs @@ -11,37 +11,53 @@ using Serilog.Events; namespace PepperDash.Essentials.Devices.Common.Displays { - /// - /// Represents a BasicIrDisplay - /// - public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced + /// + /// Represents a BasicIrDisplay + /// + public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced { - /// - /// Gets or sets the IrPort - /// + /// + /// Gets or sets the IrPort + /// public IrOutputPortController IrPort { get; private set; } - /// - /// Gets or sets the IrPulseTime - /// + /// + /// Gets or sets the IrPulseTime + /// public ushort IrPulseTime { get; set; } - protected Func PowerIsOnFeedbackFunc - { - get { return () => _PowerIsOn; } - } + /// + /// Gets the power is on feedback function + /// + protected Func PowerIsOnFeedbackFunc + { + get { return () => _PowerIsOn; } + } + /// + /// Gets the is cooling down feedback function + /// protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } + /// + /// Gets the is warming up feedback function + /// protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } - bool _PowerIsOn; + bool _PowerIsOn; bool _IsWarmingUp; bool _IsCoolingDown; + /// + /// Initializes a new instance of the BasicIrDisplay class + /// + /// The device key + /// The device name + /// The IR output port + /// The path to the IR driver file public BasicIrDisplay(string key, string name, IROutputPort port, string irDriverFilepath) : base(key, name) { @@ -53,74 +69,74 @@ namespace PepperDash.Essentials.Devices.Common.Displays InputPorts.AddRange(new RoutingPortCollection { - new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, + new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, new Action(Hdmi1), this, false), - new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, + new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, new Action(Hdmi2), this, false), - new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video, + new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, new Action(Hdmi3), this, false), - new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.Audio | eRoutingSignalType.Video, + new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, new Action(Hdmi4), this, false), - new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, + new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, new Action(Component1), this, false), - new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, + new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, new Action(Video1), this, false), - new RoutingInputPort(RoutingPortNames.AntennaIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, + new RoutingInputPort(RoutingPortNames.AntennaIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, new Action(Antenna), this, false), }); } - /// - /// Hdmi1 method - /// + /// + /// Hdmi1 method + /// public void Hdmi1() { IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_1, IrPulseTime); } - /// - /// Hdmi2 method - /// + /// + /// Hdmi2 method + /// public void Hdmi2() { IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_2, IrPulseTime); } - /// - /// Hdmi3 method - /// + /// + /// Hdmi3 method + /// public void Hdmi3() { IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_3, IrPulseTime); } - /// - /// Hdmi4 method - /// + /// + /// Hdmi4 method + /// public void Hdmi4() { IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_4, IrPulseTime); } - /// - /// Component1 method - /// + /// + /// Component1 method + /// public void Component1() { IrPort.Pulse(IROutputStandardCommands.IROut_COMPONENT_1, IrPulseTime); } - /// - /// Video1 method - /// + /// + /// Video1 method + /// public void Video1() { IrPort.Pulse(IROutputStandardCommands.IROut_VIDEO_1, IrPulseTime); } - /// - /// Antenna method - /// + /// + /// Antenna method + /// public void Antenna() { IrPort.Pulse(IROutputStandardCommands.IROut_ANTENNA, IrPulseTime); @@ -128,31 +144,31 @@ namespace PepperDash.Essentials.Devices.Common.Displays #region IPower Members - /// - /// PowerOn method - /// - /// + /// + /// PowerOn method + /// + /// public override void PowerOn() { IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime); - _PowerIsOn = true; + _PowerIsOn = true; } - /// - /// PowerOff method - /// + /// + /// PowerOff method + /// public override void PowerOff() { - _PowerIsOn = false; + _PowerIsOn = false; IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime); } - /// - /// PowerToggle method - /// + /// + /// PowerToggle method + /// public override void PowerToggle() { - _PowerIsOn = false; + _PowerIsOn = false; IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime); } @@ -160,25 +176,25 @@ namespace PepperDash.Essentials.Devices.Common.Displays #region IBasicVolumeControls Members - /// - /// VolumeUp method - /// + /// + /// VolumeUp method + /// public void VolumeUp(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_PLUS, pressRelease); } - /// - /// VolumeDown method - /// + /// + /// VolumeDown method + /// public void VolumeDown(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_MINUS, pressRelease); } - /// - /// MuteToggle method - /// + /// + /// MuteToggle method + /// public void MuteToggle() { IrPort.Pulse(IROutputStandardCommands.IROut_MUTE, 200); @@ -190,7 +206,8 @@ namespace PepperDash.Essentials.Devices.Common.Displays { _IsWarmingUp = true; IsWarmingUpFeedback.FireUpdate(); - new CTimer(o => { + new CTimer(o => + { _IsWarmingUp = false; IsWarmingUpFeedback.FireUpdate(); }, 10000); @@ -213,13 +230,13 @@ namespace PepperDash.Essentials.Devices.Common.Displays /// Typically called by the discovery routing algorithm. /// /// A delegate containing the input selector method to call - /// - /// ExecuteSwitch method - /// - /// + /// + /// ExecuteSwitch method + /// + /// public override void ExecuteSwitch(object inputSelector) { - Debug.LogMessage(LogEventLevel.Verbose, this, "Switching to input '{0}'", (inputSelector as Action).ToString()); + Debug.LogMessage(LogEventLevel.Verbose, this, "Switching to input '{0}'", (inputSelector as Action).ToString()); Action finishSwitch = () => { @@ -246,42 +263,45 @@ namespace PepperDash.Essentials.Devices.Common.Displays #endregion - /// - /// LinkToApi method - /// - public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); - } + /// + /// LinkToApi method + /// + public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); + } } - /// - /// Represents a BasicIrDisplayFactory - /// - public class BasicIrDisplayFactory : EssentialsDeviceFactory - { - public BasicIrDisplayFactory() - { - TypeNames = new List() { "basicirdisplay" }; - } + /// + /// Represents a BasicIrDisplayFactory + /// + public class BasicIrDisplayFactory : EssentialsDeviceFactory + { + /// + /// Initializes a new instance of the BasicIrDisplayFactory class + /// + public BasicIrDisplayFactory() + { + TypeNames = new List() { "basicirdisplay" }; + } - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BasicIrDisplay Device"); - var ir = IRPortHelper.GetIrPort(dc.Properties); - if (ir != null) - { - var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName); - display.IrPulseTime = 200; // Set default pulse time for IR commands. - return display; - } + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BasicIrDisplay Device"); + var ir = IRPortHelper.GetIrPort(dc.Properties); + if (ir != null) + { + var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName); + display.IrPulseTime = 200; // Set default pulse time for IR commands. + return display; + } - return null; - } - } + return null; + } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs b/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs index c94591a3..5db03a30 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs @@ -19,7 +19,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays /// Abstract base class for display devices that provides common display functionality /// including power control, input switching, and routing capabilities. /// - public abstract class DisplayBase : EssentialsDevice, IDisplay, ICurrentSources + public abstract class DisplayBase : EssentialsDevice, IDisplay, ICurrentSources, IHasFeedback { private RoutingInputPort _currentInputPort; @@ -73,13 +73,11 @@ namespace PepperDash.Essentials.Devices.Common.Displays var handler = CurrentSourceChange; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.WillChange); + handler?.Invoke(_CurrentSourceInfo, ChangeType.WillChange); _CurrentSourceInfo = value; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.DidChange); + handler?.Invoke(_CurrentSourceInfo, ChangeType.DidChange); } } SourceListItem _CurrentSourceInfo; @@ -160,6 +158,9 @@ namespace PepperDash.Essentials.Devices.Common.Displays IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc); IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc); + Feedbacks.Add(IsCoolingDownFeedback); + Feedbacks.Add(IsWarmingUpFeedback); + InputPorts = new RoutingPortCollection(); CurrentSources = new Dictionary @@ -194,17 +195,8 @@ namespace PepperDash.Essentials.Devices.Common.Displays /// Gets the collection of feedback objects for this display device. /// /// - public virtual FeedbackCollection Feedbacks - { - get - { - return new FeedbackCollection - { - IsCoolingDownFeedback, - IsWarmingUpFeedback - }; - } - } + public virtual FeedbackCollection Feedbacks { get; private set; } = new FeedbackCollection(); + /// /// Executes a switch to the specified input on the display device. Must be implemented by derived classes. @@ -252,47 +244,35 @@ namespace PepperDash.Essentials.Devices.Common.Displays /// The join map configuration for the device. protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap) { - Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - Debug.LogMessage(LogEventLevel.Information, "Linking to Display: {0}", displayDevice.Name); + this.LogDebug("Linking to Trilist {ipId}", trilist.ID.ToString("X")); + this.LogDebug("Linking to Display: {displayName}", displayDevice.Name); trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name; - var commMonitor = displayDevice as ICommunicationMonitor; - if (commMonitor != null) + if (displayDevice is ICommunicationMonitor commMonitor) { commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); } + // TODO: revisit this as there could be issues with this approach var inputNumber = 0; var inputKeys = new List(); - var inputNumberFeedback = new IntFeedback(() => inputNumber); + var inputNumberFeedback = new IntFeedback("inputNumber", () => inputNumber); - // Two way feedbacks - var twoWayDisplay = displayDevice as TwoWayDisplayBase; + // Add input number feedback to the device feedback collection to keep it around... + Feedbacks.Add(inputNumberFeedback); - if (twoWayDisplay != null) + // Two way feedbacks + if (displayDevice is TwoWayDisplayBase twoWayDisplay) { trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true); - twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Information, "CurrentInputFeedback_OutputChange {0}", a.StringValue); - + twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => this.LogDebug("CurrentInputFeedback_OutputChange {input}", a.StringValue); inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]); - } - // Power Off - trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () => - { - inputNumber = 102; - inputNumberFeedback.FireUpdate(); - displayDevice.PowerOff(); - }); - - var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase; - if (twoWayDisplayDevice != null) - { - twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) => + twoWayDisplay.PowerIsOnFeedback.OutputChange += (o, a) => { if (!a.BoolValue) { @@ -307,10 +287,18 @@ namespace PepperDash.Essentials.Devices.Common.Displays } }; - twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]); - twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]); + twoWayDisplay.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]); + twoWayDisplay.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]); } + // Power Off + trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () => + { + inputNumber = 102; + inputNumberFeedback.FireUpdate(); + displayDevice.PowerOff(); + }); + // PowerOn trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () => { @@ -320,44 +308,61 @@ namespace PepperDash.Essentials.Devices.Common.Displays }); - for (int i = 0; i < displayDevice.InputPorts.Count; i++) { - if (i < joinMap.InputNamesOffset.JoinSpan) + var localindex = i; + if (localindex >= joinMap.InputNamesOffset.JoinSpan) { - inputKeys.Add(displayDevice.InputPorts[i].Key); - var tempKey = inputKeys.ElementAt(i); - trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i), - () => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector)); - Debug.LogMessage(LogEventLevel.Verbose, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}", - joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString()); - trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString(); + this.LogWarning("Device has {inputCount} inputs. The Join Map allows up to {joinSpan} inputs. Discarding inputs {discardStart} - {discardEnd} from bridge.", + displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, localindex + 1, displayDevice.InputPorts.Count); + + continue; } else - Debug.LogMessage(LogEventLevel.Information, displayDevice, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.", - displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count); + { + inputKeys.Add(displayDevice.InputPorts[localindex].Key); + + var tempKey = inputKeys.ElementAt(localindex); + + trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + localindex), () => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector)); + + this.LogDebug("Setting Input Select Action on Digital Join {joinNumber} to Input: {input}", joinMap.InputSelectOffset.JoinNumber + localindex, displayDevice.InputPorts[tempKey].Key); + + trilist.SetString((uint)(joinMap.InputNamesOffset.JoinNumber + localindex), displayDevice.InputPorts[localindex].Key); + } } - Debug.LogMessage(LogEventLevel.Verbose, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect); - trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) => + this.LogDebug("Setting Input Select Action on Analog Join {inputSelectJoin}", joinMap.InputSelect); + + trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (requestedInput) => { - if (a == 0) + if (requestedInput == 0) { displayDevice.PowerOff(); inputNumber = 0; + return; } - else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber) + + // using 1-based indexing for inputs coming from SIMPL, so need to check if the input is <= the count, not < + if (requestedInput > 0 && requestedInput <= displayDevice.InputPorts.Count && requestedInput != inputNumber) { - displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector); - inputNumber = a; + displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(requestedInput - 1).Selector); + + inputNumber = requestedInput; + + return; } - else if (a == 102) + + if (requestedInput == 102) { displayDevice.PowerToggle(); - + return; + } + + if (displayDevice is TwoWayDisplayBase) + { + inputNumberFeedback?.FireUpdate(); } - if (twoWayDisplay != null) - inputNumberFeedback.FireUpdate(); }); @@ -430,95 +435,4 @@ namespace PepperDash.Essentials.Devices.Common.Displays } } - - /// - /// Abstract base class for two-way display devices that provide feedback capabilities. - /// Extends DisplayBase with routing feedback and power control feedback functionality. - /// - public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback - { - /// - /// Gets feedback for the current input selection on the display. - /// - public StringFeedback CurrentInputFeedback { get; private set; } - - /// - /// Abstract function that must be implemented by derived classes to provide the current input feedback value. - /// Must be implemented by concrete sub-classes. - /// - abstract protected Func CurrentInputFeedbackFunc { get; } - - /// - /// Gets feedback indicating whether the display is currently powered on. - /// - public BoolFeedback PowerIsOnFeedback { get; protected set; } - - /// - /// Abstract function that must be implemented by derived classes to provide the power state feedback value. - /// Must be implemented by concrete sub-classes. - /// - abstract protected Func PowerIsOnFeedbackFunc { get; } - - /// - /// Gets the default mock display instance for testing and development purposes. - /// - public static MockDisplay DefaultDisplay - { - get - { - if (_DefaultDisplay == null) - _DefaultDisplay = new MockDisplay("default", "Default Display"); - return _DefaultDisplay; - } - } - static MockDisplay _DefaultDisplay; - - /// - /// Initializes a new instance of the TwoWayDisplayBase class. - /// - /// The unique key identifier for this display device. - /// The friendly name for this display device. - public TwoWayDisplayBase(string key, string name) - : base(key, name) - { - CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc); - - WarmupTime = 7000; - CooldownTime = 15000; - - PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc); - - Feedbacks.Add(CurrentInputFeedback); - Feedbacks.Add(PowerIsOnFeedback); - - PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; - - } - - void PowerIsOnFeedback_OutputChange(object sender, EventArgs e) - { - if (UsageTracker != null) - { - if (PowerIsOnFeedback.BoolValue) - UsageTracker.StartDeviceUsage(); - else - UsageTracker.EndDeviceUsage(); - } - } - - /// - /// Event that is raised when a numeric switch change occurs on the display. - /// - public event EventHandler NumericSwitchChange; - - /// - /// Raise an event when the status of a switch object changes. - /// - /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType - protected void OnSwitchChange(RoutingNumericEventArgs e) - { - var newEvent = NumericSwitchChange; - if (newEvent != null) newEvent(this, e); - } - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/InputInterfaces.cs b/src/PepperDash.Essentials.Devices.Common/Displays/InputInterfaces.cs index abc2e7f1..b4314c6b 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/InputInterfaces.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/InputInterfaces.cs @@ -1,38 +1,89 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; namespace PepperDash.Essentials.Devices.Displays { /// /// Defines the contract for IInputHdmi1 /// - public interface IInputHdmi1 { void InputHdmi1(); } + [Obsolete()] + public interface IInputHdmi1 + { + /// + /// Switches to HDMI 1 input + /// + void InputHdmi1(); + } + /// /// Defines the contract for IInputHdmi2 /// - public interface IInputHdmi2 { void InputHdmi2(); } + [Obsolete()] + public interface IInputHdmi2 + { + /// + /// Switches to HDMI 2 input + /// + void InputHdmi2(); + } + /// /// Defines the contract for IInputHdmi3 /// - public interface IInputHdmi3 { void InputHdmi3(); } + [Obsolete()] + public interface IInputHdmi3 + { + /// + /// Switches to HDMI 3 input + /// + void InputHdmi3(); + } + /// /// Defines the contract for IInputHdmi4 /// - public interface IInputHdmi4 { void InputHdmi4(); } + [Obsolete()] + public interface IInputHdmi4 + { + /// + /// Switches to HDMI 4 input + /// + void InputHdmi4(); + } + /// /// Defines the contract for IInputDisplayPort1 /// - public interface IInputDisplayPort1 { void InputDisplayPort1(); } + [Obsolete()] + public interface IInputDisplayPort1 + { + /// + /// Switches to DisplayPort 1 input + /// + void InputDisplayPort1(); + } + /// /// Defines the contract for IInputDisplayPort2 /// - public interface IInputDisplayPort2 { void InputDisplayPort2(); } + [Obsolete()] + public interface IInputDisplayPort2 + { + /// + /// Switches to DisplayPort 2 input + /// + void InputDisplayPort2(); + } + /// /// Defines the contract for IInputVga1 /// - public interface IInputVga1 { void InputVga1(); } + [Obsolete()] + public interface IInputVga1 + { + /// + /// Switches to VGA 1 input + /// + void InputVga1(); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs index 976dfdc3..6f46b1a4 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs @@ -16,16 +16,19 @@ namespace PepperDash.Essentials.Devices.Common.Displays /// Represents a MockDisplay /// public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs, IRoutingSinkWithSwitchingWithInputPort, IHasPowerControlWithFeedback - { + { /// /// Gets or sets the Inputs /// public ISelectableItems Inputs { get; private set; } - bool _PowerIsOn; - bool _IsWarmingUp; - bool _IsCoolingDown; + bool _PowerIsOn; + bool _IsWarmingUp; + bool _IsCoolingDown; + /// + /// Gets the power is on feedback function + /// protected override Func PowerIsOnFeedbackFunc { get @@ -34,8 +37,12 @@ namespace PepperDash.Essentials.Devices.Common.Displays { return _PowerIsOn; }; - } } - protected override Func IsCoolingDownFeedbackFunc + } + } + /// + /// Gets the is cooling down feedback function + /// + protected override Func IsCoolingDownFeedbackFunc { get { @@ -45,7 +52,10 @@ namespace PepperDash.Essentials.Devices.Common.Displays }; } } - protected override Func IsWarmingUpFeedbackFunc + /// + /// Gets the is warming up feedback function + /// + protected override Func IsWarmingUpFeedbackFunc { get { @@ -55,120 +65,128 @@ namespace PepperDash.Essentials.Devices.Common.Displays }; } } + /// + /// Gets the current input feedback function + /// protected override Func CurrentInputFeedbackFunc { get { return () => Inputs.CurrentItem; } } int VolumeHeldRepeatInterval = 200; ushort VolumeInterval = 655; - ushort _FakeVolumeLevel = 31768; - bool _IsMuted; + ushort _FakeVolumeLevel = 31768; + bool _IsMuted; - public MockDisplay(string key, string name) - : base(key, name) - { + /// + /// Initializes a new instance of the MockDisplay class + /// + /// The device key + /// The device name + public MockDisplay(string key, string name) + : base(key, name) + { Inputs = new MockDisplayInputs { Items = new Dictionary - { - { "HDMI1", new MockDisplayInput ( "HDMI1", "HDMI 1",this ) }, - { "HDMI2", new MockDisplayInput ("HDMI2", "HDMI 2",this ) }, - { "HDMI3", new MockDisplayInput ("HDMI3", "HDMI 3",this ) }, - { "HDMI4", new MockDisplayInput ("HDMI4", "HDMI 4",this )}, - { "DP", new MockDisplayInput ("DP", "DisplayPort", this ) } - } + { + { "HDMI1", new MockDisplayInput ( "HDMI1", "HDMI 1",this ) }, + { "HDMI2", new MockDisplayInput ("HDMI2", "HDMI 2",this ) }, + { "HDMI3", new MockDisplayInput ("HDMI3", "HDMI 3",this ) }, + { "HDMI4", new MockDisplayInput ("HDMI4", "HDMI 4",this )}, + { "DP", new MockDisplayInput ("DP", "DisplayPort", this ) } + } }; - Inputs.CurrentItemChanged += (o, a) => CurrentInputFeedback.FireUpdate(); - - var hdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, "HDMI1", this); - var hdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, "HDMI2", this); - var hdmiIn3 = new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, "HDMI3", this); - var hdmiIn4 = new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, "HDMI4", this); - var dpIn = new RoutingInputPort(RoutingPortNames.DisplayPortIn, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.DisplayPort, "DP", this); - InputPorts.AddRange(new[] { hdmiIn1, hdmiIn2, hdmiIn3, hdmiIn4, dpIn }); + Inputs.CurrentItemChanged += (o, a) => CurrentInputFeedback.FireUpdate(); - VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; }); - MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted); + var hdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, "HDMI1", this); + var hdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, "HDMI2", this); + var hdmiIn3 = new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, "HDMI3", this); + var hdmiIn4 = new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, "HDMI4", this); + var dpIn = new RoutingInputPort(RoutingPortNames.DisplayPortIn, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.DisplayPort, "DP", this); + InputPorts.AddRange(new[] { hdmiIn1, hdmiIn2, hdmiIn3, hdmiIn4, dpIn }); + + VolumeLevelFeedback = new IntFeedback("volume", () => { return _FakeVolumeLevel; }); + MuteFeedback = new BoolFeedback("muteOn", () => _IsMuted); WarmupTime = 10000; CooldownTime = 10000; - } + } - /// - /// PowerOn method - /// - /// - public override void PowerOn() - { - if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) - { - _IsWarmingUp = true; - IsWarmingUpFeedback.InvokeFireUpdate(); - // Fake power-up cycle - WarmupTimer = new CTimer(o => - { - _IsWarmingUp = false; - _PowerIsOn = true; - IsWarmingUpFeedback.InvokeFireUpdate(); - PowerIsOnFeedback.InvokeFireUpdate(); - }, WarmupTime); - } - } + /// + /// PowerOn method + /// + /// + public override void PowerOn() + { + if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) + { + _IsWarmingUp = true; + IsWarmingUpFeedback.InvokeFireUpdate(); + // Fake power-up cycle + WarmupTimer = new CTimer(o => + { + _IsWarmingUp = false; + _PowerIsOn = true; + IsWarmingUpFeedback.InvokeFireUpdate(); + PowerIsOnFeedback.InvokeFireUpdate(); + }, WarmupTime); + } + } - /// - /// PowerOff method - /// - /// - public override void PowerOff() - { - // If a display has unreliable-power off feedback, just override this and - // remove this check. - if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) - { - _IsCoolingDown = true; - IsCoolingDownFeedback.InvokeFireUpdate(); - // Fake cool-down cycle - CooldownTimer = new CTimer(o => - { - Debug.LogMessage(LogEventLevel.Verbose, "Cooldown timer ending", this); - _IsCoolingDown = false; - IsCoolingDownFeedback.InvokeFireUpdate(); + /// + /// PowerOff method + /// + /// + public override void PowerOff() + { + // If a display has unreliable-power off feedback, just override this and + // remove this check. + if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) + { + _IsCoolingDown = true; + IsCoolingDownFeedback.InvokeFireUpdate(); + // Fake cool-down cycle + CooldownTimer = new CTimer(o => + { + Debug.LogMessage(LogEventLevel.Verbose, "Cooldown timer ending", this); + _IsCoolingDown = false; + IsCoolingDownFeedback.InvokeFireUpdate(); _PowerIsOn = false; PowerIsOnFeedback.InvokeFireUpdate(); - }, CooldownTime); - } - } - - /// - /// PowerToggle method - /// - /// - public override void PowerToggle() - { - if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue) - PowerOff(); - else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue) - PowerOn(); - } + }, CooldownTime); + } + } - /// - /// ExecuteSwitch method - /// - /// - public override void ExecuteSwitch(object selector) - { + /// + /// PowerToggle method + /// + /// + public override void PowerToggle() + { + if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue) + PowerOff(); + else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue) + PowerOn(); + } + + /// + /// ExecuteSwitch method + /// + /// + public override void ExecuteSwitch(object selector) + { try { Debug.LogMessage(LogEventLevel.Verbose, "ExecuteSwitch: {0}", this, selector); - if (!_PowerIsOn) - { - PowerOn(); - } + if (!_PowerIsOn) + { + PowerOn(); + } if (!Inputs.Items.TryGetValue(selector.ToString(), out var input)) return; @@ -184,13 +202,14 @@ namespace PepperDash.Essentials.Devices.Common.Displays if (inputPort == null) { - Debug.LogMessage(LogEventLevel.Verbose, "Unable to find input port for selector {selector}", this, selector); + Debug.LogMessage(LogEventLevel.Verbose, "Unable to find input port for selector {selector}", this, selector); return; } Debug.LogMessage(LogEventLevel.Verbose, "Setting current input port to {inputPort}", this, inputPort); CurrentInputPort = inputPort; - } catch (Exception ex) + } + catch (Exception ex) { Debug.LogMessage(ex, "Error making switch: {Exception}", this, ex); } @@ -201,14 +220,14 @@ namespace PepperDash.Essentials.Devices.Common.Displays /// public void SetInput(string selector) { - ISelectableItem currentInput = null; + ISelectableItem currentInput = null; + + try + { + currentInput = Inputs.Items.SingleOrDefault(Inputs => Inputs.Value.IsSelected).Value; + } + catch { } - try - { - currentInput = Inputs.Items.SingleOrDefault(Inputs => Inputs.Value.IsSelected).Value; - } - catch { } - if (currentInput != null) { @@ -216,12 +235,12 @@ namespace PepperDash.Essentials.Devices.Common.Displays currentInput.IsSelected = false; } - if (!Inputs.Items.TryGetValue(selector, out var input)) + if (!Inputs.Items.TryGetValue(selector, out var input)) return; - input.IsSelected = true; + input.IsSelected = true; - Inputs.CurrentItem = selector; + Inputs.CurrentItem = selector; } @@ -232,37 +251,37 @@ namespace PepperDash.Essentials.Devices.Common.Displays /// public IntFeedback VolumeLevelFeedback { get; private set; } - /// - /// SetVolume method - /// - public void SetVolume(ushort level) - { - _FakeVolumeLevel = level; - VolumeLevelFeedback.InvokeFireUpdate(); - } + /// + /// SetVolume method + /// + public void SetVolume(ushort level) + { + _FakeVolumeLevel = level; + VolumeLevelFeedback.InvokeFireUpdate(); + } - /// - /// MuteOn method - /// - public void MuteOn() - { - _IsMuted = true; - MuteFeedback.InvokeFireUpdate(); - } + /// + /// MuteOn method + /// + public void MuteOn() + { + _IsMuted = true; + MuteFeedback.InvokeFireUpdate(); + } - /// - /// MuteOff method - /// - public void MuteOff() - { - _IsMuted = false; - MuteFeedback.InvokeFireUpdate(); - } + /// + /// MuteOff method + /// + public void MuteOff() + { + _IsMuted = false; + MuteFeedback.InvokeFireUpdate(); + } - /// - /// Gets or sets the MuteFeedback - /// - public BoolFeedback MuteFeedback { get; private set; } + /// + /// Gets or sets the MuteFeedback + /// + public BoolFeedback MuteFeedback { get; private set; } #endregion @@ -273,74 +292,77 @@ namespace PepperDash.Essentials.Devices.Common.Displays /// VolumeUp method /// public void VolumeUp(bool pressRelease) - { + { //while (pressRelease) //{ - Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Down {0}", pressRelease); - if (pressRelease) - { - var newLevel = _FakeVolumeLevel + VolumeInterval; - SetVolume((ushort)newLevel); - CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); - } + Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Down {0}", pressRelease); + if (pressRelease) + { + var newLevel = _FakeVolumeLevel + VolumeInterval; + SetVolume((ushort)newLevel); + CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); + } //} - } + } - /// - /// VolumeDown method - /// - public void VolumeDown(bool pressRelease) - { + /// + /// VolumeDown method + /// + public void VolumeDown(bool pressRelease) + { //while (pressRelease) //{ - Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Up {0}", pressRelease); - if (pressRelease) - { - var newLevel = _FakeVolumeLevel - VolumeInterval; - SetVolume((ushort)newLevel); - CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); - } + Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Up {0}", pressRelease); + if (pressRelease) + { + var newLevel = _FakeVolumeLevel - VolumeInterval; + SetVolume((ushort)newLevel); + CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); + } //} - } + } - /// - /// MuteToggle method - /// - public void MuteToggle() - { - _IsMuted = !_IsMuted; - MuteFeedback.InvokeFireUpdate(); - } + /// + /// MuteToggle method + /// + public void MuteToggle() + { + _IsMuted = !_IsMuted; + MuteFeedback.InvokeFireUpdate(); + } - #endregion + #endregion - /// - /// LinkToApi method - /// - public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); - } + /// + /// LinkToApi method + /// + public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); + } } - /// - /// Represents a MockDisplayFactory - /// - public class MockDisplayFactory : EssentialsDeviceFactory - { - public MockDisplayFactory() - { - TypeNames = new List() { "mockdisplay" , "mockdisplay2" }; - } + /// + /// Represents a MockDisplayFactory + /// + public class MockDisplayFactory : EssentialsDeviceFactory + { + /// + /// Initializes a new instance of the MockDisplayFactory class + /// + public MockDisplayFactory() + { + TypeNames = new List() { "mockdisplay", "mockdisplay2" }; + } - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device"); - return new MockDisplay(dc.Key, dc.Name); - } - } + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device"); + return new MockDisplay(dc.Key, dc.Name); + } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs index 5b2ee2e2..b30963ac 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs @@ -1,10 +1,6 @@ -using PepperDash.Essentials.Core.DeviceTypeInterfaces; -using System; +using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; namespace PepperDash.Essentials.Devices.Common.Displays { @@ -15,6 +11,9 @@ namespace PepperDash.Essentials.Devices.Common.Displays { private Dictionary _items; + /// + /// Gets or sets the collection of selectable items + /// public Dictionary Items { get @@ -34,8 +33,11 @@ namespace PepperDash.Essentials.Devices.Common.Displays private string _currentItem; + /// + /// Gets or sets the currently selected item + /// public string CurrentItem - { + { get { return _currentItem; @@ -51,7 +53,13 @@ namespace PepperDash.Essentials.Devices.Common.Displays } } + /// + /// Occurs when the items collection is updated + /// public event EventHandler ItemsUpdated; + /// + /// Occurs when the current item changes + /// public event EventHandler CurrentItemChanged; } @@ -63,7 +71,10 @@ namespace PepperDash.Essentials.Devices.Common.Displays private MockDisplay _parent; private bool _isSelected; - + + /// + /// Gets or sets a value indicating whether this input is selected + /// public bool IsSelected { get @@ -91,8 +102,17 @@ namespace PepperDash.Essentials.Devices.Common.Displays /// public string Key { get; set; } + /// + /// Occurs when this item is updated + /// public event EventHandler ItemUpdated; + /// + /// Initializes a new instance of the MockDisplayInput class + /// + /// The input key + /// The input name + /// The parent mock display public MockDisplayInput(string key, string name, MockDisplay parent) { Key = key; @@ -107,7 +127,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays { if (!_parent.PowerIsOnFeedback.BoolValue) _parent.PowerOn(); - foreach(var input in _parent.Inputs.Items) + foreach (var input in _parent.Inputs.Items) { input.Value.IsSelected = input.Key == this.Key; } diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs index 204fee42..9163c2a3 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs @@ -1,14 +1,11 @@ using System; using System.Collections.Generic; using Crestron.SimplSharp; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.CrestronIO; using PepperDash.Essentials.Core.DeviceTypeInterfaces; -using PepperDash.Essentials.Devices.Common; using Serilog.Events; namespace PepperDash.Essentials.Devices.Common.Shades @@ -28,6 +25,9 @@ namespace PepperDash.Essentials.Devices.Common.Shades ISwitchedOutput LowerRelay; ISwitchedOutput LatchedRelay; + /// + /// Gets or sets the InUpPosition + /// public bool InUpPosition { get { return _isInUpPosition; } @@ -41,10 +41,12 @@ namespace PepperDash.Essentials.Devices.Common.Shades } private bool _isInUpPosition { get; set; } + /// /// Gets or sets the Type /// public eScreenLiftControlType Type { get; private set; } + /// /// Gets or sets the Mode /// @@ -54,13 +56,20 @@ namespace PepperDash.Essentials.Devices.Common.Shades /// Gets or sets the DisplayDeviceKey /// public string DisplayDeviceKey { get; private set; } + /// /// Gets or sets the IsInUpPosition /// public BoolFeedback IsInUpPosition { get; private set; } + /// + /// Event that fires when the position changes + /// public event EventHandler PositionChanged; + /// + /// Constructor for ScreenLiftController + /// public ScreenLiftController(string key, string name, ScreenLiftControllerConfigProperties config) : base(key, name) { @@ -69,7 +78,7 @@ namespace PepperDash.Essentials.Devices.Common.Shades Mode = Config.Mode; Type = Config.Type; - IsInUpPosition = new BoolFeedback(() => _isInUpPosition); + IsInUpPosition = new BoolFeedback("isInUpPosition", () => _isInUpPosition); switch (Mode) { @@ -206,14 +215,14 @@ namespace PepperDash.Essentials.Devices.Common.Shades /// /// Attempts to get the port on teh specified device from config /// - /// + /// /// ISwitchedOutput GetSwitchedOutputFromDevice(string relayKey) { var portDevice = DeviceManager.GetDeviceForKey(relayKey); if (portDevice != null) { - return (portDevice as ISwitchedOutput); + return portDevice as ISwitchedOutput; } else { @@ -238,58 +247,14 @@ namespace PepperDash.Essentials.Devices.Common.Shades } - /// - /// Represents a ScreenLiftControllerConfigProperties - /// - public class ScreenLiftControllerConfigProperties - { - [JsonProperty("displayDeviceKey")] - /// - /// Gets or sets the DisplayDeviceKey - /// - public string DisplayDeviceKey { get; set; } - - [JsonProperty("type")] - [JsonConverter(typeof(StringEnumConverter))] - /// - /// Gets or sets the Type - /// - public eScreenLiftControlType Type { get; set; } - - [JsonProperty("mode")] - [JsonConverter(typeof(StringEnumConverter))] - /// - /// Gets or sets the Mode - /// - public eScreenLiftControlMode Mode { get; set; } - - [JsonProperty("relays")] - public Dictionary Relays { get; set; } - - } - /// - /// Represents a ScreenLiftRelaysConfig - /// - public class ScreenLiftRelaysConfig - { - [JsonProperty("deviceKey")] - /// - /// Gets or sets the DeviceKey - /// - public string DeviceKey { get; set; } - - [JsonProperty("pulseTimeInMs")] - /// - /// Gets or sets the PulseTimeInMs - /// - public int PulseTimeInMs { get; set; } - } - /// /// Represents a ScreenLiftControllerFactory /// public class ScreenLiftControllerFactory : EssentialsDeviceFactory { + /// + /// Constructor for ScreenLiftControllerFactory + /// public ScreenLiftControllerFactory() { TypeNames = new List() { "screenliftcontroller" }; @@ -307,13 +272,4 @@ namespace PepperDash.Essentials.Devices.Common.Shades return new ScreenLiftController(dc.Key, dc.Name, props); } } - - /// - /// Enumeration of eScreenLiftControlMode values - /// - public enum eScreenLiftControlMode - { - momentary, - latched - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftControllerConfigProperties.cs b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftControllerConfigProperties.cs new file mode 100644 index 00000000..9de1faa0 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftControllerConfigProperties.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; + +namespace PepperDash.Essentials.Devices.Common.Shades +{ + /// + /// Represents a ScreenLiftControllerConfigProperties + /// + public class ScreenLiftControllerConfigProperties + { + + /// + /// Gets or sets the DisplayDeviceKey + /// + [JsonProperty("displayDeviceKey")] + public string DisplayDeviceKey { get; set; } + + /// + /// Gets or sets the Type + /// + [JsonProperty("type")] + [JsonConverter(typeof(StringEnumConverter))] + public eScreenLiftControlType Type { get; set; } + + /// + /// Gets or sets the Mode + /// + [JsonProperty("mode")] + [JsonConverter(typeof(StringEnumConverter))] + public eScreenLiftControlMode Mode { get; set; } + + /// + /// Gets or sets the Relays + /// + [JsonProperty("relays")] + public Dictionary Relays { get; set; } + + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftRelaysConfig.cs b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftRelaysConfig.cs new file mode 100644 index 00000000..4de9eb25 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftRelaysConfig.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Devices.Common.Shades +{ + /// + /// Represents a ScreenLiftRelaysConfig + /// + public class ScreenLiftRelaysConfig + { + /// + /// Gets or sets the DeviceKey + /// + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } + + /// + /// Gets or sets the PulseTimeInMs + /// + [JsonProperty("pulseTimeInMs")] + public int PulseTimeInMs { get; set; } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/TwoWayDisplayBase.cs b/src/PepperDash.Essentials.Devices.Common/Displays/TwoWayDisplayBase.cs new file mode 100644 index 00000000..226d4bbe --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Displays/TwoWayDisplayBase.cs @@ -0,0 +1,95 @@ +using System; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Devices.Common.Displays +{ + /// + /// Abstract base class for two-way display devices that provide feedback capabilities. + /// Extends DisplayBase with routing feedback and power control feedback functionality. + /// + public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback + { + /// + /// Gets feedback for the current input selection on the display. + /// + public StringFeedback CurrentInputFeedback { get; private set; } + + /// + /// Abstract function that must be implemented by derived classes to provide the current input feedback value. + /// Must be implemented by concrete sub-classes. + /// + abstract protected Func CurrentInputFeedbackFunc { get; } + + /// + /// Gets feedback indicating whether the display is currently powered on. + /// + public BoolFeedback PowerIsOnFeedback { get; protected set; } + + /// + /// Abstract function that must be implemented by derived classes to provide the power state feedback value. + /// Must be implemented by concrete sub-classes. + /// + abstract protected Func PowerIsOnFeedbackFunc { get; } + + /// + /// Gets the default mock display instance for testing and development purposes. + /// + public static MockDisplay DefaultDisplay + { + get + { + if (_DefaultDisplay == null) + _DefaultDisplay = new MockDisplay("default", "Default Display"); + return _DefaultDisplay; + } + } + static MockDisplay _DefaultDisplay; + + /// + /// Initializes a new instance of the TwoWayDisplayBase class. + /// + /// The unique key identifier for this display device. + /// The friendly name for this display device. + public TwoWayDisplayBase(string key, string name) + : base(key, name) + { + CurrentInputFeedback = new StringFeedback("currentInput", CurrentInputFeedbackFunc); + + WarmupTime = 7000; + CooldownTime = 15000; + + PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc); + + Feedbacks.Add(CurrentInputFeedback); + Feedbacks.Add(PowerIsOnFeedback); + + PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; + + } + + void PowerIsOnFeedback_OutputChange(object sender, EventArgs e) + { + if (UsageTracker != null) + { + if (PowerIsOnFeedback.BoolValue) + UsageTracker.StartDeviceUsage(); + else + UsageTracker.EndDeviceUsage(); + } + } + + /// + /// Event that is raised when a numeric switch change occurs on the display. + /// + public event EventHandler NumericSwitchChange; + + /// + /// Raise an event when the status of a switch object changes. + /// + /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType + protected void OnSwitchChange(RoutingNumericEventArgs e) + { + NumericSwitchChange?.Invoke(this, e); + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/eScreenLiftControlMode.cs b/src/PepperDash.Essentials.Devices.Common/Displays/eScreenLiftControlMode.cs new file mode 100644 index 00000000..8114ac26 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Displays/eScreenLiftControlMode.cs @@ -0,0 +1,17 @@ +namespace PepperDash.Essentials.Devices.Common.Shades +{ + /// + /// Enumeration of eScreenLiftControlMode values + /// + public enum eScreenLiftControlMode + { + /// + /// Momentary control mode for screen lift + /// + momentary, + /// + /// Latched control mode for screen lift + /// + latched + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs index 748b48bb..a44eb012 100644 --- a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs +++ b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs @@ -1,9 +1,8 @@ -using PepperDash.Core; +using System.Collections.Generic; +using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using Serilog.Events; -using System; -using System.Collections.Generic; namespace PepperDash.Essentials.Devices.Common.Generic { @@ -12,11 +11,16 @@ namespace PepperDash.Essentials.Devices.Common.Generic /// public class GenericSink : EssentialsDevice, IRoutingSinkWithInputPort { + /// + /// Initializes a new instance of the GenericSink class + /// + /// The device key + /// The device name public GenericSink(string key, string name) : base(key, name) { InputPorts = new RoutingPortCollection(); - var inputPort = new RoutingInputPort(RoutingPortNames.AnyVideoIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); + var inputPort = new RoutingInputPort(RoutingPortNames.AnyVideoIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); InputPorts.Add(inputPort); } @@ -35,10 +39,12 @@ namespace PepperDash.Essentials.Devices.Common.Generic /// /// Gets or sets the CurrentSourceInfo /// - public SourceListItem CurrentSourceInfo { + public SourceListItem CurrentSourceInfo + { get => _currentSource; - set { - if(value == _currentSource) + set + { + if (value == _currentSource) { return; } @@ -51,8 +57,14 @@ namespace PepperDash.Essentials.Devices.Common.Generic } } + /// + /// Gets the current input port + /// public RoutingInputPort CurrentInputPort => InputPorts[0]; + /// + /// Event fired when the current source changes + /// public event SourceInfoChangeHandler CurrentSourceChange; } @@ -61,6 +73,9 @@ namespace PepperDash.Essentials.Devices.Common.Generic /// public class GenericSinkFactory : EssentialsDeviceFactory { + /// + /// Initializes a new instance of the GenericSinkFactory class + /// public GenericSinkFactory() { TypeNames = new List() { "genericsink", "genericdestination" }; diff --git a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs index 6cf359e8..3d0f1304 100644 --- a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs +++ b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; +using System.Collections.Generic; using PepperDash.Core; using PepperDash.Essentials.Core; @@ -13,38 +7,43 @@ using Serilog.Events; namespace PepperDash.Essentials.Devices.Common { - /// - /// Represents a GenericSource - /// - public class GenericSource : EssentialsDevice, IUiDisplayInfo, IRoutingSource, IUsageTracking - { + /// + /// Represents a GenericSource + /// + public class GenericSource : EssentialsDevice, IUiDisplayInfo, IRoutingSource, IUsageTracking + { - /// - /// Gets or sets the DisplayUiType - /// - public uint DisplayUiType { get { return DisplayUiConstants.TypeNoControls; } } + /// + /// Gets or sets the DisplayUiType + /// + public uint DisplayUiType { get { return DisplayUiConstants.TypeNoControls; } } + /// + /// Initializes a new instance of the GenericSource class + /// + /// The device key + /// The device name public GenericSource(string key, string name) - : base(key, name) - { + : base(key, name) + { - AnyOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - OutputPorts = new RoutingPortCollection { AnyOut }; - } + AnyOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null, this); + OutputPorts = new RoutingPortCollection { AnyOut }; + } - #region IRoutingOutputs Members + #region IRoutingOutputs Members - /// - /// Gets or sets the AnyOut - /// - public RoutingOutputPort AnyOut { get; private set; } - /// - /// Gets or sets the OutputPorts - /// - public RoutingPortCollection OutputPorts { get; private set; } + /// + /// Gets or sets the AnyOut + /// + public RoutingOutputPort AnyOut { get; private set; } + /// + /// Gets or sets the OutputPorts + /// + public RoutingPortCollection OutputPorts { get; private set; } - #endregion + #endregion #region IUsageTracking Members @@ -54,13 +53,16 @@ namespace PepperDash.Essentials.Devices.Common public UsageTracking UsageTracker { get; set; } #endregion - } + } /// /// Represents a GenericSourceFactory /// public class GenericSourceFactory : EssentialsDeviceFactory { + /// + /// Initializes a new instance of the GenericSourceFactory class + /// public GenericSourceFactory() { TypeNames = new List() { "genericsource" }; diff --git a/src/PepperDash.Essentials.Devices.Common/Lighting/LightingBase.cs b/src/PepperDash.Essentials.Devices.Common/Lighting/LightingBase.cs index d98d8804..9dd3b816 100644 --- a/src/PepperDash.Essentials.Devices.Common/Lighting/LightingBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Lighting/LightingBase.cs @@ -3,9 +3,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; using PepperDash.Core; @@ -16,134 +13,165 @@ using Serilog.Events; namespace PepperDash.Essentials.Devices.Common.Lighting { - public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes - { - #region ILightingScenes Members - - public event EventHandler LightingSceneChange; - - /// - /// Gets or sets the LightingScenes - /// - public List LightingScenes { get; protected set; } - - /// - /// Gets or sets the CurrentLightingScene - /// - public LightingScene CurrentLightingScene { get; protected set; } - /// - /// Gets or sets the CurrentLightingSceneFeedback + /// Base class for lighting devices that support scenes /// - public IntFeedback CurrentLightingSceneFeedback { get; protected set; } + public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes + { + #region ILightingScenes Members - #endregion + /// + /// Event fired when lighting scene changes + /// + public event EventHandler LightingSceneChange; - protected LightingBase(string key, string name) - : base(key, name) - { - LightingScenes = new List(); + /// + /// Gets or sets the LightingScenes + /// + public List LightingScenes { get; protected set; } - CurrentLightingScene = new LightingScene(); - //CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); }); - } + /// + /// Gets or sets the CurrentLightingScene + /// + public LightingScene CurrentLightingScene { get; protected set; } - public abstract void SelectScene(LightingScene scene); + /// + /// Gets or sets the CurrentLightingSceneFeedback + /// + public IntFeedback CurrentLightingSceneFeedback { get; protected set; } - /// - /// SimulateSceneSelect method - /// - public void SimulateSceneSelect(string sceneName) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Simulating selection of scene '{0}'", sceneName); + #endregion - var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName)); + /// + /// Initializes a new instance of the LightingBase class + /// + /// The device key + /// The device name + protected LightingBase(string key, string name) + : base(key, name) + { + LightingScenes = new List(); - if (scene != null) - { - CurrentLightingScene = scene; - OnLightingSceneChange(); - } - } + CurrentLightingScene = new LightingScene(); + //CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); }); + } - /// - /// Sets the IsActive property on each scene and fires the LightingSceneChange event - /// - protected void OnLightingSceneChange() - { - foreach (var scene in LightingScenes) - { - if (scene == CurrentLightingScene) - scene.IsActive = true; - - else - scene.IsActive = false; - } - LightingSceneChange?.Invoke(this, new LightingSceneChangeEventArgs(CurrentLightingScene)); - } + /// + /// Selects the specified lighting scene + /// + /// The lighting scene to select + public abstract void SelectScene(LightingScene scene); - protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart, - string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new GenericLightingJoinMap(joinStart); + /// + /// SimulateSceneSelect method + /// + public void SimulateSceneSelect(string sceneName) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Simulating selection of scene '{0}'", sceneName); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName)); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } - - return LinkLightingToApi(lightingDevice, trilist, joinMap); - } - - protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap) + if (scene != null) { - Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + CurrentLightingScene = scene; + OnLightingSceneChange(); + } + } - Debug.LogMessage(LogEventLevel.Information, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString()); + /// + /// Sets the IsActive property on each scene and fires the LightingSceneChange event + /// + protected void OnLightingSceneChange() + { + foreach (var scene in LightingScenes) + { + if (scene == CurrentLightingScene) + scene.IsActive = true; - // GenericLighitng Actions & FeedBack - trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u])); + else + scene.IsActive = false; + } + LightingSceneChange?.Invoke(this, new LightingSceneChangeEventArgs(CurrentLightingScene)); + } - var sceneIndex = 0; + /// + /// Links the lighting device to API with join map configuration + /// + /// The lighting device to link + /// The trilist to link to + /// The starting join number + /// The join map key + /// The EISC API bridge + /// The configured join map + protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart, + string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new GenericLightingJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + return LinkLightingToApi(lightingDevice, trilist, joinMap); + } + + /// + /// Links the lighting device to API using an existing join map + /// + /// The lighting device to link + /// The trilist to link to + /// The join map to use + /// The join map used for linking + protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap) + { + Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + Debug.LogMessage(LogEventLevel.Information, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString()); + + // GenericLighitng Actions & FeedBack + trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u])); + + var sceneIndex = 0; + foreach (var scene in lightingDevice.LightingScenes) + { + var index = sceneIndex; + + trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index])); + scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]); + trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; + trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; + + sceneIndex++; + } + + trilist.OnlineStatusChange += (sender, args) => + { + if (!args.DeviceOnLine) return; + + sceneIndex = 0; foreach (var scene in lightingDevice.LightingScenes) { var index = sceneIndex; - trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index])); - scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]); trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; + scene.IsActiveFeedback.FireUpdate(); sceneIndex++; } + }; - trilist.OnlineStatusChange += (sender, args) => - { - if (!args.DeviceOnLine) return; - - sceneIndex = 0; - foreach (var scene in lightingDevice.LightingScenes) - { - var index = sceneIndex; - - trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; - trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; - scene.IsActiveFeedback.FireUpdate(); - - sceneIndex++; - } - }; - - return joinMap; - } + return joinMap; } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleSpaceRoom.cs b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleSpaceRoom.cs index 6e5e3797..ecce473e 100644 --- a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleSpaceRoom.cs +++ b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleSpaceRoom.cs @@ -9,10 +9,20 @@ namespace PepperDash.Essentials.Devices.Common.Room public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IHasDefaultDisplay, IHasCurrentVolumeControls, IRoomOccupancy, IEmergency, IMicrophonePrivacy { + /// + /// Gets whether to exclude this room from global functions + /// bool ExcludeFromGlobalFunctions { get; } + /// + /// Runs the route action for the given routeKey and sourceListKey + /// + /// The route key void RunRouteAction(string routeKey); + /// + /// Gets the PropertiesConfig + /// EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleVtc1Room.cs b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleVtc1Room.cs index 98d01956..5547f595 100644 --- a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleVtc1Room.cs +++ b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleVtc1Room.cs @@ -12,18 +12,40 @@ namespace PepperDash.Essentials.Devices.Common.Room public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback, IRoomOccupancy, IEmergency, IMicrophonePrivacy { + /// + /// Gets the PropertiesConfig + /// EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } + /// + /// Gets whether to exclude this room from global functions + /// bool ExcludeFromGlobalFunctions { get; } + /// + /// Runs the route action for the given routeKey and sourceListKey + /// + /// The route key void RunRouteAction(string routeKey); + /// + /// Gets the ScheduleSource + /// IHasScheduleAwareness ScheduleSource { get; } + /// + /// Gets the InCallFeedback + /// new BoolFeedback InCallFeedback { get; } + /// + /// Gets the PrivacyModeIsOnFeedback + /// new BoolFeedback PrivacyModeIsOnFeedback { get; } + /// + /// Gets the DefaultCodecRouteString + /// string DefaultCodecRouteString { get; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsRoomPropertiesConfig.cs index d536242e..e45be6e0 100644 --- a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsRoomPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsRoomPropertiesConfig.cs @@ -1,9 +1,4 @@ using PepperDash.Essentials.Room.Config; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace PepperDash.Essentials.Devices.Common.Room { @@ -12,6 +7,9 @@ namespace PepperDash.Essentials.Devices.Common.Room /// public interface IEssentialsRoomPropertiesConfig { + /// + /// Gets the PropertiesConfig + /// EssentialsRoomPropertiesConfig PropertiesConfig { get; } } } diff --git a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsTechRoom.cs b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsTechRoom.cs index e651011a..9301f37d 100644 --- a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsTechRoom.cs +++ b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsTechRoom.cs @@ -1,9 +1,9 @@ -using PepperDash.Essentials.Core; +using System.Collections.Generic; +using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Devices.Common.Displays; using PepperDash.Essentials.Room.Config; -using System.Collections.Generic; -using TwoWayDisplayBase = PepperDash.Essentials.Devices.Common.Displays.TwoWayDisplayBase; namespace PepperDash.Essentials.Devices.Common.Room @@ -11,15 +11,31 @@ namespace PepperDash.Essentials.Devices.Common.Room /// /// Defines the contract for IEssentialsTechRoom /// - public interface IEssentialsTechRoom:IEssentialsRoom, ITvPresetsProvider,IBridgeAdvanced,IRunDirectRouteAction + public interface IEssentialsTechRoom : IEssentialsRoom, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction { + /// + /// Gets the PropertiesConfig + /// EssentialsTechRoomConfig PropertiesConfig { get; } + + /// + /// Gets the Tuners + /// Dictionary Tuners { get; } + /// + /// Gets the Displays + /// Dictionary Displays { get; } + /// + /// Powers on the room + /// void RoomPowerOn(); + /// + /// Powers off the room + /// void RoomPowerOff(); } } diff --git a/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBase.cs b/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBase.cs index db21a03a..7d49b9b7 100644 --- a/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBase.cs @@ -1,38 +1,31 @@ - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Core.Presets; using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Core.Presets; using Serilog.Events; namespace PepperDash.Essentials.Devices.Common { - [Description("Wrapper class for an IR Set Top Box")] /// /// Represents a IRSetTopBoxBase + /// Wrapper class for an IR Set Top Box /// + [Description("Wrapper class for an IR Set Top Box")] public class IRSetTopBoxBase : EssentialsBridgeableDevice, ISetTopBoxControls, IRoutingSource, IRoutingOutputs, IUsageTracking, IHasPowerControl, ITvPresetsProvider - { - /// - /// Gets or sets the IrPort - /// + { + /// + /// Gets or sets the IrPort + /// public IrOutputPortController IrPort { get; private set; } - /// - /// Gets or sets the DisplayUiType - /// - public uint DisplayUiType { get { return DisplayUiConstants.TypeDirecTv; } } + /// + /// Gets or sets the DisplayUiType + /// + public uint DisplayUiType { get { return DisplayUiConstants.TypeDirecTv; } } /// /// Gets or sets the IrPulseTime /// @@ -60,11 +53,18 @@ namespace PepperDash.Essentials.Devices.Common /// public DevicePresetsModel TvPresets { get; private set; } - public IRSetTopBoxBase(string key, string name, IrOutputPortController portCont, + /// + /// Initializes a new instance of the class + /// + /// The unique identifier for the device + /// The name of the device + /// The IR output port controller + /// The properties configuration + public IRSetTopBoxBase(string key, string name, IrOutputPortController portCont, SetTopBoxPropertiesConfig props) - : base(key, name) - { - IrPort = portCont; + : base(key, name) + { + IrPort = portCont; IrPulseTime = 200; if (props.IrPulseTime > 0) @@ -72,424 +72,433 @@ namespace PepperDash.Essentials.Devices.Common IrPulseTime = (ushort)props.IrPulseTime; } - DeviceManager.AddDevice(portCont); + DeviceManager.AddDevice(portCont); HasPresets = props.HasPresets; HasDvr = props.HasDvr; HasDpad = props.HasDpad; HasNumeric = props.HasNumeric; - HasKeypadAccessoryButton1 = true; - KeypadAccessoryButton1Command = "Dash"; - KeypadAccessoryButton1Label = "-"; - - HasKeypadAccessoryButton2 = true; - KeypadAccessoryButton2Command = "KEYPAD_ENTER"; - KeypadAccessoryButton2Label = "Enter"; - - AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio, - eRoutingPortConnectionType.DigitalAudio, null, this); - OutputPorts = new RoutingPortCollection { AnyVideoOut, AnyAudioOut }; - } - - /// - /// LoadPresets method - /// - public void LoadPresets(string filePath) - { - TvPresets = new DevicePresetsModel(Key + "-presets", this, filePath); - DeviceManager.AddDevice(TvPresets); - } - - - #region ISetTopBoxControls Members - - /// - /// DvrList method - /// - public void DvrList(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_DVR, pressRelease); - } - - /// - /// Replay method - /// - public void Replay(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_REPLAY, pressRelease); - } - - #endregion - - #region IDPad Members - - /// - /// Up method - /// - public void Up(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_UP_ARROW, pressRelease); - } - - /// - /// Down method - /// - public void Down(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_DN_ARROW, pressRelease); - } - - /// - /// Left method - /// - public void Left(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_LEFT_ARROW, pressRelease); - } - - /// - /// Right method - /// - public void Right(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_RIGHT_ARROW, pressRelease); - } - - /// - /// Select method - /// - public void Select(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_ENTER, pressRelease); - } - - /// - /// Menu method - /// - public void Menu(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_MENU, pressRelease); - } - - /// - /// Exit method - /// - public void Exit(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_EXIT, pressRelease); - } - - #endregion - - #region INumericKeypad Members - - /// - /// Digit0 method - /// - public void Digit0(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_0, pressRelease); - } - - /// - /// Digit1 method - /// - public void Digit1(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_1, pressRelease); - } - - /// - /// Digit2 method - /// - public void Digit2(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_2, pressRelease); - } - - /// - /// Digit3 method - /// - public void Digit3(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_3, pressRelease); - } - - /// - /// Digit4 method - /// - public void Digit4(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_4, pressRelease); - } - - /// - /// Digit5 method - /// - public void Digit5(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_5, pressRelease); - } - - /// - /// Digit6 method - /// - public void Digit6(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_6, pressRelease); - } - - /// - /// Digit7 method - /// - public void Digit7(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_7, pressRelease); - } - - /// - /// Digit8 method - /// - public void Digit8(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_8, pressRelease); - } - - /// - /// Digit9 method - /// - public void Digit9(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_9, pressRelease); - } - - /// - /// Gets or sets the HasKeypadAccessoryButton1 - /// - public bool HasKeypadAccessoryButton1 { get; set; } - - /// - /// Defaults to "-" - /// - public string KeypadAccessoryButton1Label { get; set; } - - - /// - /// Defaults to "Dash" - /// - public string KeypadAccessoryButton1Command { get; set; } - - public void KeypadAccessoryButton1(bool pressRelease) - { - IrPort.PressRelease(KeypadAccessoryButton1Command, pressRelease); - } - - /// - /// Gets or sets the HasKeypadAccessoryButton2 - /// - public bool HasKeypadAccessoryButton2 { get; set; } - - /// - /// Defaults to "Enter" - /// - public string KeypadAccessoryButton2Label { get; set; } - - - /// - /// Defaults to "Enter" - /// - public string KeypadAccessoryButton2Command { get; set; } - - public void KeypadAccessoryButton2(bool pressRelease) - { - IrPort.PressRelease(KeypadAccessoryButton2Command, pressRelease); - } - - #endregion - - #region ISetTopBoxNumericKeypad Members - - /// - /// Dash method - /// - public void Dash(bool pressRelease) - { - IrPort.PressRelease("dash", pressRelease); - } - - /// - /// Corresponds to "numericEnter" IR command - /// - public void KeypadEnter(bool pressRelease) - { - IrPort.PressRelease("numericEnter", pressRelease); - } - - #endregion - - #region IChannelFunctions Members - - public void ChannelUp(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_CH_PLUS, pressRelease); - } - - /// - /// ChannelDown method - /// - public void ChannelDown(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_CH_MINUS, pressRelease); - } - - /// - /// LastChannel method - /// - public void LastChannel(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_LAST, pressRelease); - } - - /// - /// Guide method - /// - public void Guide(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_GUIDE, pressRelease); - } - - /// - /// Info method - /// - public void Info(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_INFO, pressRelease); - } - - #endregion - - #region IColorFunctions Members - - /// - /// Red method - /// - public void Red(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_RED, pressRelease); - } - - /// - /// Green method - /// - public void Green(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_GREEN, pressRelease); - } - - /// - /// Yellow method - /// - public void Yellow(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_YELLOW, pressRelease); - } - - /// - /// Blue method - /// - public void Blue(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_BLUE, pressRelease); - } - - #endregion - - #region IRoutingOutputs Members - - /// - /// Gets or sets the AnyVideoOut - /// - public RoutingOutputPort AnyVideoOut { get; private set; } - /// - /// Gets or sets the AnyAudioOut - /// - public RoutingOutputPort AnyAudioOut { get; private set; } - /// - /// Gets or sets the OutputPorts - /// - public RoutingPortCollection OutputPorts { get; private set; } - - #endregion - - #region ITransport Members - - /// - /// ChapMinus method - /// - public void ChapMinus(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_REPLAY, pressRelease); - } - - /// - /// ChapPlus method - /// - public void ChapPlus(bool pressRelease) - { - } - - /// - /// FFwd method - /// - public void FFwd(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_FSCAN, pressRelease); - } - - /// - /// Pause method - /// - public void Pause(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease); - } - - /// - /// Play method - /// - public void Play(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_PLAY, pressRelease); - } - - /// - /// Record method - /// - public void Record(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_RECORD, pressRelease); - } - - /// - /// Rewind method - /// - public void Rewind(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease); - } - - /// - /// Stop method - /// - public void Stop(bool pressRelease) - { - IrPort.PressRelease(IROutputStandardCommands.IROut_STOP, pressRelease); - } - - #endregion + HasKeypadAccessoryButton1 = true; + KeypadAccessoryButton1Command = "Dash"; + KeypadAccessoryButton1Label = "-"; + + HasKeypadAccessoryButton2 = true; + KeypadAccessoryButton2Command = "KEYPAD_ENTER"; + KeypadAccessoryButton2Label = "Enter"; + + AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null, this); + AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio, + eRoutingPortConnectionType.DigitalAudio, null, this); + OutputPorts = new RoutingPortCollection { AnyVideoOut, AnyAudioOut }; + } + + /// + /// LoadPresets method + /// + public void LoadPresets(string filePath) + { + TvPresets = new DevicePresetsModel(Key + "-presets", this, filePath); + DeviceManager.AddDevice(TvPresets); + } + + + #region ISetTopBoxControls Members + + /// + /// DvrList method + /// + public void DvrList(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_DVR, pressRelease); + } + + /// + /// Replay method + /// + public void Replay(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_REPLAY, pressRelease); + } + + #endregion + + #region IDPad Members + + /// + /// Up method + /// + public void Up(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_UP_ARROW, pressRelease); + } + + /// + /// Down method + /// + public void Down(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_DN_ARROW, pressRelease); + } + + /// + /// Left method + /// + public void Left(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_LEFT_ARROW, pressRelease); + } + + /// + /// Right method + /// + public void Right(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_RIGHT_ARROW, pressRelease); + } + + /// + /// Select method + /// + public void Select(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_ENTER, pressRelease); + } + + /// + /// Menu method + /// + public void Menu(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_MENU, pressRelease); + } + + /// + /// Exit method + /// + public void Exit(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_EXIT, pressRelease); + } + + #endregion + + #region INumericKeypad Members + + /// + /// Digit0 method + /// + public void Digit0(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_0, pressRelease); + } + + /// + /// Digit1 method + /// + public void Digit1(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_1, pressRelease); + } + + /// + /// Digit2 method + /// + public void Digit2(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_2, pressRelease); + } + + /// + /// Digit3 method + /// + public void Digit3(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_3, pressRelease); + } + + /// + /// Digit4 method + /// + public void Digit4(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_4, pressRelease); + } + + /// + /// Digit5 method + /// + public void Digit5(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_5, pressRelease); + } + + /// + /// Digit6 method + /// + public void Digit6(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_6, pressRelease); + } + + /// + /// Digit7 method + /// + public void Digit7(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_7, pressRelease); + } + + /// + /// Digit8 method + /// + public void Digit8(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_8, pressRelease); + } + + /// + /// Digit9 method + /// + public void Digit9(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_9, pressRelease); + } + + /// + /// Gets or sets the HasKeypadAccessoryButton1 + /// + public bool HasKeypadAccessoryButton1 { get; set; } + + /// + /// Defaults to "-" + /// + public string KeypadAccessoryButton1Label { get; set; } + + + /// + /// Defaults to "Dash" + /// + public string KeypadAccessoryButton1Command { get; set; } + + /// + /// Presses the KeypadAccessoryButton1 + /// + public void KeypadAccessoryButton1(bool pressRelease) + { + IrPort.PressRelease(KeypadAccessoryButton1Command, pressRelease); + } + + /// + /// Gets or sets the HasKeypadAccessoryButton2 + /// + public bool HasKeypadAccessoryButton2 { get; set; } + + /// + /// Defaults to "Enter" + /// + public string KeypadAccessoryButton2Label { get; set; } + + + /// + /// Defaults to "Enter" + /// + public string KeypadAccessoryButton2Command { get; set; } + + /// + /// Presses the KeypadAccessoryButton2 + /// + public void KeypadAccessoryButton2(bool pressRelease) + { + IrPort.PressRelease(KeypadAccessoryButton2Command, pressRelease); + } + + #endregion + + #region ISetTopBoxNumericKeypad Members + + /// + /// Dash method + /// + public void Dash(bool pressRelease) + { + IrPort.PressRelease("dash", pressRelease); + } + + /// + /// Corresponds to "numericEnter" IR command + /// + public void KeypadEnter(bool pressRelease) + { + IrPort.PressRelease("numericEnter", pressRelease); + } + + #endregion + + #region IChannelFunctions Members + + /// + /// ChannelUp method + /// + public void ChannelUp(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_CH_PLUS, pressRelease); + } + + /// + /// ChannelDown method + /// + public void ChannelDown(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_CH_MINUS, pressRelease); + } + + /// + /// LastChannel method + /// + public void LastChannel(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_LAST, pressRelease); + } + + /// + /// Guide method + /// + public void Guide(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_GUIDE, pressRelease); + } + + /// + /// Info method + /// + public void Info(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_INFO, pressRelease); + } + + #endregion + + #region IColorFunctions Members + + /// + /// Red method + /// + public void Red(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_RED, pressRelease); + } + + /// + /// Green method + /// + public void Green(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_GREEN, pressRelease); + } + + /// + /// Yellow method + /// + public void Yellow(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_YELLOW, pressRelease); + } + + /// + /// Blue method + /// + public void Blue(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_BLUE, pressRelease); + } + + #endregion + + #region IRoutingOutputs Members + + /// + /// Gets or sets the AnyVideoOut + /// + public RoutingOutputPort AnyVideoOut { get; private set; } + /// + /// Gets or sets the AnyAudioOut + /// + public RoutingOutputPort AnyAudioOut { get; private set; } + /// + /// Gets or sets the OutputPorts + /// + public RoutingPortCollection OutputPorts { get; private set; } + + #endregion + + #region ITransport Members + + /// + /// ChapMinus method + /// + public void ChapMinus(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_REPLAY, pressRelease); + } + + /// + /// ChapPlus method + /// + public void ChapPlus(bool pressRelease) + { + } + + /// + /// FFwd method + /// + public void FFwd(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_FSCAN, pressRelease); + } + + /// + /// Pause method + /// + public void Pause(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease); + } + + /// + /// Play method + /// + public void Play(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_PLAY, pressRelease); + } + + /// + /// Record method + /// + public void Record(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_RECORD, pressRelease); + } + + /// + /// Rewind method + /// + public void Rewind(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease); + } + + /// + /// Stop method + /// + public void Stop(bool pressRelease) + { + IrPort.PressRelease(IROutputStandardCommands.IROut_STOP, pressRelease); + } + + #endregion #region IUsageTracking Members @@ -528,12 +537,12 @@ namespace PepperDash.Essentials.Devices.Common #endregion - /// - /// LinkToApi method - /// - /// - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { + /// + /// LinkToApi method + /// + /// + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { var joinMap = new SetTopBoxControllerJoinMap(joinStart); var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); @@ -561,8 +570,7 @@ namespace PepperDash.Essentials.Devices.Common }); - var stbBase = this as ISetTopBoxControls; - if (stbBase != null) + if (this is ISetTopBoxControls stbBase) { trilist.BooleanInput[joinMap.HasDpad.JoinNumber].BoolValue = stbBase.HasDpad; trilist.BooleanInput[joinMap.HasNumeric.JoinNumber].BoolValue = stbBase.HasNumeric; @@ -575,16 +583,14 @@ namespace PepperDash.Essentials.Devices.Common trilist.SetStringSigAction(joinMap.LoadPresets.JoinNumber, stbBase.LoadPresets); } - var stbPower = this as IHasPowerControl; - if (stbPower != null) + if (this is IHasPowerControl stbPower) { trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, stbPower.PowerOn); trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, stbPower.PowerOff); trilist.SetSigTrueAction(joinMap.PowerToggle.JoinNumber, stbPower.PowerToggle); } - var stbDPad = this as IDPad; - if (stbDPad != null) + if (this is IDPad stbDPad) { trilist.SetBoolSigAction(joinMap.Up.JoinNumber, stbDPad.Up); trilist.SetBoolSigAction(joinMap.Down.JoinNumber, stbDPad.Down); @@ -595,8 +601,7 @@ namespace PepperDash.Essentials.Devices.Common trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbDPad.Exit); } - var stbChannel = this as IChannel; - if (stbChannel != null) + if (this is IChannel stbChannel) { trilist.SetBoolSigAction(joinMap.ChannelUp.JoinNumber, stbChannel.ChannelUp); trilist.SetBoolSigAction(joinMap.ChannelDown.JoinNumber, stbChannel.ChannelDown); @@ -606,8 +611,7 @@ namespace PepperDash.Essentials.Devices.Common trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbChannel.Exit); } - var stbColor = this as IColor; - if (stbColor != null) + if (this is IColor stbColor) { trilist.SetBoolSigAction(joinMap.Red.JoinNumber, stbColor.Red); trilist.SetBoolSigAction(joinMap.Green.JoinNumber, stbColor.Green); @@ -615,8 +619,7 @@ namespace PepperDash.Essentials.Devices.Common trilist.SetBoolSigAction(joinMap.Blue.JoinNumber, stbColor.Blue); } - var stbKeypad = this as ISetTopBoxNumericKeypad; - if (stbKeypad != null) + if (this is ISetTopBoxNumericKeypad stbKeypad) { trilist.StringInput[joinMap.KeypadAccessoryButton1Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton1Label; trilist.StringInput[joinMap.KeypadAccessoryButton2Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton2Label; @@ -640,8 +643,7 @@ namespace PepperDash.Essentials.Devices.Common trilist.SetBoolSigAction(joinMap.KeypadEnter.JoinNumber, stbKeypad.KeypadEnter); } - var stbTransport = this as ITransport; - if (stbTransport != null) + if (this is ITransport stbTransport) { trilist.SetBoolSigAction(joinMap.Play.JoinNumber, stbTransport.Play); trilist.SetBoolSigAction(joinMap.Pause.JoinNumber, stbTransport.Pause); @@ -652,35 +654,6 @@ namespace PepperDash.Essentials.Devices.Common trilist.SetBoolSigAction(joinMap.Stop.JoinNumber, stbTransport.Stop); trilist.SetBoolSigAction(joinMap.Record.JoinNumber, stbTransport.Record); } - } - } - - /// - /// Represents a IRSetTopBoxBaseFactory - /// - public class IRSetTopBoxBaseFactory : EssentialsDeviceFactory - { - public IRSetTopBoxBaseFactory() - { - TypeNames = new List() { "settopbox" }; - } - - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new SetTopBox Device"); - var irCont = IRPortHelper.GetIrOutputPortController(dc); - var config = dc.Properties.ToObject(); - var stb = new IRSetTopBoxBase(dc.Key, dc.Name, irCont, config); - - var listName = dc.Properties.Value("presetsList"); - if (listName != null) - stb.LoadPresets(listName); - return stb; - } } diff --git a/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBaseFactory.cs b/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBaseFactory.cs new file mode 100644 index 00000000..5b122a6a --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBaseFactory.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using Serilog.Events; + +namespace PepperDash.Essentials.Devices.Common +{ + /// + /// Represents a IRSetTopBoxBaseFactory + /// + public class IRSetTopBoxBaseFactory : EssentialsDeviceFactory + { + /// + /// Initializes a new instance of the class + /// + public IRSetTopBoxBaseFactory() + { + TypeNames = new List() { "settopbox" }; + } + + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new SetTopBox Device"); + var irCont = IRPortHelper.GetIrOutputPortController(dc); + var config = dc.Properties.ToObject(); + var stb = new IRSetTopBoxBase(dc.Key, dc.Name, irCont, config); + + var listName = dc.Properties.Value("presetsList"); + if (listName != null) + stb.LoadPresets(listName); + return stb; + + } + } + +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/SetTopBox/SetTopBoxPropertiesConfig.cs b/src/PepperDash.Essentials.Devices.Common/SetTopBox/SetTopBoxPropertiesConfig.cs index a2ec7e54..193b41e7 100644 --- a/src/PepperDash.Essentials.Devices.Common/SetTopBox/SetTopBoxPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/SetTopBox/SetTopBoxPropertiesConfig.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Core; +using PepperDash.Core; namespace PepperDash.Essentials.Devices.Common { diff --git a/src/PepperDash.Essentials.Devices.Common/Shades/RelayControlledShade.cs b/src/PepperDash.Essentials.Devices.Common/Shades/RelayControlledShade.cs index ad094703..e0080627 100644 --- a/src/PepperDash.Essentials.Devices.Common/Shades/RelayControlledShade.cs +++ b/src/PepperDash.Essentials.Devices.Common/Shades/RelayControlledShade.cs @@ -27,6 +27,12 @@ namespace PepperDash.Essentials.Devices.Common.Shades /// public string StopOrPresetButtonLabel { get; set; } + /// + /// Initializes a new instance of the RelayControlledShade class + /// + /// The device key + /// The device name + /// The relay controlled shade configuration public RelayControlledShade(string key, string name, RelayControlledShadeConfigProperties config) : base(key, name) { @@ -157,6 +163,9 @@ namespace PepperDash.Essentials.Devices.Common.Shades /// public class RelayControlledShadeFactory : EssentialsDeviceFactory { + /// + /// Initializes a new instance of the RelayControlledShadeFactory class + /// public RelayControlledShadeFactory() { TypeNames = new List() { "relaycontrolledshade" }; diff --git a/src/PepperDash.Essentials.Devices.Common/Shades/ShadeBase.cs b/src/PepperDash.Essentials.Devices.Common/Shades/ShadeBase.cs index 2c506750..ba3d67dd 100644 --- a/src/PepperDash.Essentials.Devices.Common/Shades/ShadeBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Shades/ShadeBase.cs @@ -1,10 +1,18 @@ -using PepperDash.Essentials.Core.Shades; -using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Shades; namespace PepperDash.Essentials.Devices.Common.Shades { + /// + /// Base class for shade devices + /// public abstract class ShadeBase : EssentialsDevice, IShadesOpenCloseStop { + /// + /// Initializes a new instance of the ShadeBase class + /// + /// The device key + /// The device name public ShadeBase(string key, string name) : base(key, name) { @@ -13,8 +21,17 @@ namespace PepperDash.Essentials.Devices.Common.Shades #region iShadesOpenClose Members + /// + /// Opens the shade + /// public abstract void Open(); + /// + /// Stops the shade + /// public abstract void Stop(); + /// + /// Closes the shade + /// public abstract void Close(); #endregion diff --git a/src/PepperDash.Essentials.Devices.Common/Shades/ShadeController.cs b/src/PepperDash.Essentials.Devices.Common/Shades/ShadeController.cs index 9d28fe98..dc8cb125 100644 --- a/src/PepperDash.Essentials.Devices.Common/Shades/ShadeController.cs +++ b/src/PepperDash.Essentials.Devices.Common/Shades/ShadeController.cs @@ -14,8 +14,17 @@ namespace PepperDash.Essentials.Devices.Common.Shades { ShadeControllerConfigProperties Config; + /// + /// Gets the collection of shades controlled by this controller + /// public List Shades { get; private set; } + /// + /// Initializes a new instance of the ShadeController class + /// + /// The device key + /// The device name + /// The shade controller configuration public ShadeController(string key, string name, ShadeControllerConfigProperties config) : base(key, name) { @@ -76,6 +85,9 @@ namespace PepperDash.Essentials.Devices.Common.Shades /// public class ShadeControllerFactory : EssentialsDeviceFactory { + /// + /// Initializes a new instance of the ShadeControllerFactory class + /// public ShadeControllerFactory() { TypeNames = new List() { "shadecontroller" }; diff --git a/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPc.cs b/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPc.cs index c96e6f01..afe47814 100644 --- a/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPc.cs +++ b/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPc.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Crestron.SimplSharp; using PepperDash.Core; @@ -22,6 +21,9 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec /// public RoutingInputPort AnyVideoIn { get; private set; } + /// + /// Gets the CurrentInputPort + /// public RoutingInputPort CurrentInputPort => AnyVideoIn; #region IRoutingInputs Members @@ -33,6 +35,11 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec #endregion + /// + /// Initializes a new instance of the class + /// + /// The device key + /// The device name public BlueJeansPc(string key, string name) : base(key, name) { @@ -177,30 +184,12 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec } SourceListItem _CurrentSourceInfo; + /// + /// Event fired when the current source changes + /// public event SourceInfoChangeHandler CurrentSourceChange; #endregion } - /// - /// Represents a BlueJeansPcFactory - /// - public class BlueJeansPcFactory : EssentialsDeviceFactory - { - public BlueJeansPcFactory() - { - TypeNames = new List() { "bluejeanspc" }; - } - - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BlueJeansPc Device"); - return new SoftCodec.BlueJeansPc(dc.Key, dc.Name); - } - } - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPcFactory.cs b/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPcFactory.cs new file mode 100644 index 00000000..75f39bbd --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPcFactory.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using Serilog.Events; + + +namespace PepperDash.Essentials.Devices.Common.SoftCodec +{ + /// + /// Represents a BlueJeansPcFactory + /// + public class BlueJeansPcFactory : EssentialsDeviceFactory + { + /// + /// Initializes a new instance of the class + /// + public BlueJeansPcFactory() + { + TypeNames = new List() { "bluejeanspc" }; + } + + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BlueJeansPc Device"); + return new BlueJeansPc(dc.Key, dc.Name); + } + } + +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs index f00fb9ce..f8a8f640 100644 --- a/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs +++ b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs @@ -1,10 +1,7 @@ -using Newtonsoft.Json; +using System.Linq; using PepperDash.Core; using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Config; using Serilog.Events; -using System.Collections.Generic; -using System.Linq; namespace PepperDash.Essentials.Devices.Common.SoftCodec { @@ -18,7 +15,8 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec /// /// Gets or sets the CurrentInputPort /// - public RoutingInputPort CurrentInputPort { + public RoutingInputPort CurrentInputPort + { get => _currentInputPort; set { @@ -28,19 +26,25 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec } } + /// + /// Initializes a new instance of the class + /// + /// The device key + /// The device name + /// The device properties public GenericSoftCodec(string key, string name, GenericSoftCodecProperties props) : base(key, name) { InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); - for(var i = 1; i <= props.OutputCount; i++) + for (var i = 1; i <= props.OutputCount; i++) { var outputPort = new RoutingOutputPort($"output{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); OutputPorts.Add(outputPort); } - for(var i = 1; i<= props.ContentInputCount; i++) + for (var i = 1; i <= props.ContentInputCount; i++) { var inputPort = new RoutingInputPort($"contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this); @@ -52,7 +56,7 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec return; } - for(var i = 1; i <=props.CameraInputCount; i++) + for (var i = 1; i <= props.CameraInputCount; i++) { var cameraPort = new RoutingInputPort($"cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this); @@ -72,7 +76,11 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec /// /// Gets or sets the CurrentSourceInfoKey /// - public string CurrentSourceInfoKey { get ; set; } + public string CurrentSourceInfoKey { get; set; } + + /// + /// Gets or sets the CurrentSourceInfo + /// public SourceListItem CurrentSourceInfo { get @@ -97,7 +105,14 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec SourceListItem _CurrentSourceInfo; + /// + /// Event fired when the current source changes + /// public event SourceInfoChangeHandler CurrentSourceChange; + + /// + /// Event fired when the input changes + /// public event InputChangedEventHandler InputChanged; /// @@ -107,7 +122,7 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec { var inputPort = InputPorts.FirstOrDefault(p => p.Selector == inputSelector); - if(inputPort == null) + if (inputPort == null) { Debug.LogMessage(LogEventLevel.Warning, "No input port found for selector {inputSelector}", inputSelector); return; @@ -116,58 +131,4 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec CurrentInputPort = inputPort; } } - - /// - /// Represents a GenericSoftCodecProperties - /// - public class GenericSoftCodecProperties - { - [JsonProperty("hasCameraInputs")] - /// - /// Gets or sets the HasCameraInputs - /// - public bool HasCameraInputs { get; set; } - - [JsonProperty("cameraInputCount")] - /// - /// Gets or sets the CameraInputCount - /// - public int CameraInputCount { get; set; } - - [JsonProperty("contentInputCount")] - /// - /// Gets or sets the ContentInputCount - /// - public int ContentInputCount { get; set; } - - [JsonProperty("contentOutputCount")] - /// - /// Gets or sets the OutputCount - /// - public int OutputCount { get; set; } - } - - /// - /// Represents a GenericSoftCodecFactory - /// - public class GenericSoftCodecFactory: EssentialsDeviceFactory - { - public GenericSoftCodecFactory() - { - TypeNames = new List { "genericsoftcodec" }; - } - - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Generic SoftCodec Device"); - - var props = dc.Properties.ToObject(); - - return new GenericSoftCodec(dc.Key, dc.Name, props); - } - } } diff --git a/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodecFactory.cs b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodecFactory.cs new file mode 100644 index 00000000..51fa5240 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodecFactory.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using Serilog.Events; + +namespace PepperDash.Essentials.Devices.Common.SoftCodec +{ + /// + /// Represents a GenericSoftCodecFactory + /// + public class GenericSoftCodecFactory : EssentialsDeviceFactory + { + /// + /// Initializes a new instance of the class + /// + public GenericSoftCodecFactory() + { + TypeNames = new List { "genericsoftcodec" }; + } + + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Generic SoftCodec Device"); + + var props = dc.Properties.ToObject(); + + return new GenericSoftCodec(dc.Key, dc.Name, props); + } + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodecProperties.cs b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodecProperties.cs new file mode 100644 index 00000000..70ee19e9 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodecProperties.cs @@ -0,0 +1,34 @@ +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Devices.Common.SoftCodec +{ + /// + /// Represents a GenericSoftCodecProperties + /// + public class GenericSoftCodecProperties + { + /// + /// Gets or sets the HasCameraInputs + /// + [JsonProperty("hasCameraInputs")] + public bool HasCameraInputs { get; set; } + + /// + /// Gets or sets the CameraInputCount + /// + [JsonProperty("cameraInputCount")] + public int CameraInputCount { get; set; } + + /// + /// Gets or sets the ContentInputCount + /// + [JsonProperty("contentInputCount")] + public int ContentInputCount { get; set; } + + /// + /// Gets or sets the OutputCount + /// + [JsonProperty("contentOutputCount")] + public int OutputCount { get; set; } + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPc.cs b/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPc.cs index 48586bd2..e2ef1c09 100644 --- a/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPc.cs +++ b/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPc.cs @@ -1,71 +1,74 @@ -using System; -using System.Collections.Generic; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Config; -using Serilog.Events; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.Sources { - /// - /// Represents a InRoomPc - /// - public class InRoomPc : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking - { - /// - /// Gets or sets the DisplayUiType - /// - public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } } - /// - /// Gets or sets the IconName - /// - public string IconName { get; set; } - /// - /// Gets or sets the HasPowerOnFeedback - /// - public BoolFeedback HasPowerOnFeedback { get; private set; } + /// + /// Represents a InRoomPc + /// + public class InRoomPc : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking + { + /// + /// Gets or sets the DisplayUiType + /// + public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } } + /// + /// Gets or sets the IconName + /// + public string IconName { get; set; } + /// + /// Gets or sets the HasPowerOnFeedback + /// + public BoolFeedback HasPowerOnFeedback { get; private set; } - /// - /// Gets or sets the AnyVideoOut - /// - public RoutingOutputPort AnyVideoOut { get; private set; } + /// + /// Gets or sets the AnyVideoOut + /// + public RoutingOutputPort AnyVideoOut { get; private set; } - #region IRoutingOutputs Members + #region IRoutingOutputs Members - /// - /// Gets or sets the OutputPorts - /// - public RoutingPortCollection OutputPorts { get; private set; } + /// + /// Gets or sets the OutputPorts + /// + public RoutingPortCollection OutputPorts { get; private set; } - #endregion + #endregion - public InRoomPc(string key, string name) - : base(key, name) - { - IconName = "PC"; - HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback", - () => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus); - OutputPorts = new RoutingPortCollection(); - OutputPorts.Add(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.None, 0, this)); - } + /// + /// Initializes a new instance of the class + /// + /// + /// + public InRoomPc(string key, string name) + : base(key, name) + { + IconName = "PC"; + HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback", + () => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus); - #region IHasFeedback Members + OutputPorts = new RoutingPortCollection + { + (AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.None, 0, this)) + }; + } - /// - /// Passes through the VideoStatuses list - /// + #region IHasFeedback Members + + /// + /// Passes through the VideoStatuses list + /// public FeedbackCollection Feedbacks - { - get + { + get { var newList = new FeedbackCollection(); newList.AddRange(this.GetVideoStatuses().ToList()); return newList; } - } + } - #endregion + #endregion #region IUsageTracking Members @@ -75,27 +78,6 @@ namespace PepperDash.Essentials.Devices.Common.Sources public UsageTracking UsageTracker { get; set; } #endregion - } - - /// - /// Represents a InRoomPcFactory - /// - public class InRoomPcFactory : EssentialsDeviceFactory - { - public InRoomPcFactory() - { - TypeNames = new List() { "inroompc" }; - } - - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new InRoomPc Device"); - return new InRoomPc(dc.Key, dc.Name); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPcFactory.cs b/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPcFactory.cs new file mode 100644 index 00000000..3136fd45 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPcFactory.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using Serilog.Events; + +namespace PepperDash.Essentials.Devices.Common.Sources +{ + /// + /// Represents a InRoomPcFactory + /// + public class InRoomPcFactory : EssentialsDeviceFactory + { + /// + /// Initializes a new instance of the class + /// + public InRoomPcFactory() + { + TypeNames = new List() { "inroompc" }; + } + + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new InRoomPc Device"); + return new InRoomPc(dc.Key, dc.Name); + } + } + +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Sources/Laptop.cs b/src/PepperDash.Essentials.Devices.Common/Sources/Laptop.cs index d2da9475..83ccfc4c 100644 --- a/src/PepperDash.Essentials.Devices.Common/Sources/Laptop.cs +++ b/src/PepperDash.Essentials.Devices.Common/Sources/Laptop.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Config; -using Serilog.Events; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.Sources { @@ -11,54 +6,59 @@ namespace PepperDash.Essentials.Devices.Common.Sources /// Represents a Laptop /// public class Laptop : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking - { - /// - /// Gets or sets the DisplayUiType - /// - public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } } - /// - /// Gets or sets the IconName - /// - public string IconName { get; set; } - /// - /// Gets or sets the HasPowerOnFeedback - /// - public BoolFeedback HasPowerOnFeedback { get; private set; } + { + /// + /// Gets or sets the DisplayUiType + /// + public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } } + /// + /// Gets or sets the IconName + /// + public string IconName { get; set; } + /// + /// Gets or sets the HasPowerOnFeedback + /// + public BoolFeedback HasPowerOnFeedback { get; private set; } - /// - /// Gets or sets the AnyVideoOut - /// - public RoutingOutputPort AnyVideoOut { get; private set; } + /// + /// Gets or sets the AnyVideoOut + /// + public RoutingOutputPort AnyVideoOut { get; private set; } - #region IRoutingOutputs Members + #region IRoutingOutputs Members - /// - /// Gets or sets the OutputPorts - /// - public RoutingPortCollection OutputPorts { get; private set; } + /// + /// Gets or sets the OutputPorts + /// + public RoutingPortCollection OutputPorts { get; private set; } - #endregion + #endregion - public Laptop(string key, string name) - : base(key, name) - { - IconName = "Laptop"; + /// + /// Initializes a new instance of the Laptop class + /// + /// The device key + /// The device name + public Laptop(string key, string name) + : base(key, name) + { + IconName = "Laptop"; - HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback", - () => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus); + HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback", + () => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus); - OutputPorts = new RoutingPortCollection + OutputPorts = new RoutingPortCollection { (AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this)) }; - } + } - #region IHasFeedback Members + #region IHasFeedback Members - /// - /// Passes through the VideoStatuses list - /// + /// + /// Passes through the VideoStatuses list + /// public FeedbackCollection Feedbacks { get @@ -69,7 +69,7 @@ namespace PepperDash.Essentials.Devices.Common.Sources } } - #endregion + #endregion #region IUsageTracking Members @@ -79,26 +79,5 @@ namespace PepperDash.Essentials.Devices.Common.Sources public UsageTracking UsageTracker { get; set; } #endregion - } - - /// - /// Represents a LaptopFactory - /// - public class LaptopFactory : EssentialsDeviceFactory - { - public LaptopFactory() - { - TypeNames = new List() { "laptop" }; - } - - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Laptop Device"); - return new Laptop(dc.Key, dc.Name); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Sources/LaptopFactory.cs b/src/PepperDash.Essentials.Devices.Common/Sources/LaptopFactory.cs new file mode 100644 index 00000000..ebb072ba --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Sources/LaptopFactory.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using Serilog.Events; + +namespace PepperDash.Essentials.Devices.Common.Sources +{ + /// + /// Represents a LaptopFactory + /// + public class LaptopFactory : EssentialsDeviceFactory + { + /// + /// Initializes a new instance of the class + /// + public LaptopFactory() + { + TypeNames = new List() { "laptop" }; + } + + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Laptop Device"); + return new Laptop(dc.Key, dc.Name); + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs index 365a8271..6cf11c54 100644 --- a/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs +++ b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs @@ -1,60 +1,63 @@ - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; +using System.Linq; using System.Reflection; -using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Bridges; using Serilog.Events; namespace PepperDash.Essentials.Devices.Common { + /// + /// Represents a AppleTV + /// Wrapper class for an IR-Controlled AppleTV + /// [Description("Wrapper class for an IR-Controlled AppleTV")] - /// - /// Represents a AppleTV - /// - public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs + public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs { - /// - /// Gets or sets the IrPort - /// + /// + /// Gets or sets the IrPort + /// public IrOutputPortController IrPort { get; private set; } + + /// + /// Standard Driver Name + /// public const string StandardDriverName = "Apple_AppleTV_4th_Gen_Essentials.ir"; - /// - /// Gets or sets the DisplayUiType - /// - public uint DisplayUiType { get { return DisplayUiConstants.TypeAppleTv; } } + /// + /// Gets or sets the DisplayUiType + /// + public uint DisplayUiType { get { return DisplayUiConstants.TypeAppleTv; } } - public AppleTV(string key, string name, IrOutputPortController portCont) - : base(key, name) - { - IrPort = portCont; - DeviceManager.AddDevice(portCont); + /// + /// Initializes a new instance of the class + /// + /// The device key + /// The device name + /// The IR output port controller + public AppleTV(string key, string name, IrOutputPortController portCont) + : base(key, name) + { + IrPort = portCont; + DeviceManager.AddDevice(portCont); - HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); - AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio, - eRoutingPortConnectionType.DigitalAudio, null, this); - OutputPorts = new RoutingPortCollection { HdmiOut, AnyAudioOut }; + HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null, this); + AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio, + eRoutingPortConnectionType.DigitalAudio, null, this); + OutputPorts = new RoutingPortCollection { HdmiOut, AnyAudioOut }; PrintExpectedIrCommands(); - } + } /// /// PrintExpectedIrCommands method /// public void PrintExpectedIrCommands() { - var cmds = typeof (AppleTvIrCommands).GetFields(BindingFlags.Public | BindingFlags.Static); + var cmds = typeof(AppleTvIrCommands).GetFields(BindingFlags.Public | BindingFlags.Static); foreach (var value in cmds.Select(cmd => cmd.GetValue(null)).OfType()) { @@ -64,151 +67,158 @@ namespace PepperDash.Essentials.Devices.Common #region IDPad Members - /// - /// Up method - /// - public void Up(bool pressRelease) - { - IrPort.PressRelease(AppleTvIrCommands.Up, pressRelease); - } + /// + /// Up method + /// + public void Up(bool pressRelease) + { + IrPort.PressRelease(AppleTvIrCommands.Up, pressRelease); + } - /// - /// Down method - /// - public void Down(bool pressRelease) - { - IrPort.PressRelease(AppleTvIrCommands.Down, pressRelease); - } + /// + /// Down method + /// + public void Down(bool pressRelease) + { + IrPort.PressRelease(AppleTvIrCommands.Down, pressRelease); + } - /// - /// Left method - /// - public void Left(bool pressRelease) - { - IrPort.PressRelease(AppleTvIrCommands.Left, pressRelease); - } + /// + /// Left method + /// + public void Left(bool pressRelease) + { + IrPort.PressRelease(AppleTvIrCommands.Left, pressRelease); + } - /// - /// Right method - /// - public void Right(bool pressRelease) - { - IrPort.PressRelease(AppleTvIrCommands.Right, pressRelease); - } + /// + /// Right method + /// + public void Right(bool pressRelease) + { + IrPort.PressRelease(AppleTvIrCommands.Right, pressRelease); + } - /// - /// Select method - /// - public void Select(bool pressRelease) - { - IrPort.PressRelease(AppleTvIrCommands.Enter, pressRelease); - } + /// + /// Select method + /// + public void Select(bool pressRelease) + { + IrPort.PressRelease(AppleTvIrCommands.Enter, pressRelease); + } - /// - /// Menu method - /// - public void Menu(bool pressRelease) - { - IrPort.PressRelease(AppleTvIrCommands.Menu, pressRelease); - } + /// + /// Menu method + /// + public void Menu(bool pressRelease) + { + IrPort.PressRelease(AppleTvIrCommands.Menu, pressRelease); + } - /// - /// Exit method - /// - public void Exit(bool pressRelease) - { + /// + /// Exit method + /// + public void Exit(bool pressRelease) + { - } + } - #endregion + #endregion - #region ITransport Members + #region ITransport Members - /// - /// Play method - /// - public void Play(bool pressRelease) - { - IrPort.PressRelease(AppleTvIrCommands.PlayPause, pressRelease); - } - - /// - /// Pause method - /// - public void Pause(bool pressRelease) - { + /// + /// Play method + /// + public void Play(bool pressRelease) + { IrPort.PressRelease(AppleTvIrCommands.PlayPause, pressRelease); - } + } - /// - /// Not implemented - /// - /// - /// - /// Rewind method - /// - public void Rewind(bool pressRelease) - { - } + /// + /// Pause method + /// + public void Pause(bool pressRelease) + { + IrPort.PressRelease(AppleTvIrCommands.PlayPause, pressRelease); + } - /// - /// Not implemented - /// - /// - public void FFwd(bool pressRelease) - { - } + /// + /// Not implemented + /// + /// + /// + /// Rewind method + /// + public void Rewind(bool pressRelease) + { + } - /// - /// Not implemented - /// - /// - public void ChapMinus(bool pressRelease) - { - } + /// + /// Not implemented + /// + /// + public void FFwd(bool pressRelease) + { + } - /// - /// Not implemented - /// - /// - public void ChapPlus(bool pressRelease) - { - } + /// + /// Not implemented + /// + /// + public void ChapMinus(bool pressRelease) + { + } - /// - /// Not implemented - /// - /// - public void Stop(bool pressRelease) - { - } + /// + /// Not implemented + /// + /// + public void ChapPlus(bool pressRelease) + { + } - /// - /// Not implemented - /// - /// - public void Record(bool pressRelease) - { - } + /// + /// Not implemented + /// + /// + public void Stop(bool pressRelease) + { + } - #endregion + /// + /// Not implemented + /// + /// + public void Record(bool pressRelease) + { + } - #region IRoutingOutputs Members + #endregion - public RoutingOutputPort HdmiOut { get; private set; } - public RoutingOutputPort AnyAudioOut { get; private set; } - /// - /// Gets or sets the OutputPorts - /// - public RoutingPortCollection OutputPorts { get; private set; } + #region IRoutingOutputs Members - #endregion + /// + /// Gets the HdmiOut + /// + public RoutingOutputPort HdmiOut { get; private set; } - /// - /// LinkToApi method - /// - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { + /// + /// Gets the AnyAudioOut + /// + public RoutingOutputPort AnyAudioOut { get; private set; } + /// + /// Gets or sets the OutputPorts + /// + public RoutingPortCollection OutputPorts { get; private set; } + + #endregion + + /// + /// LinkToApi method + /// + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { var joinMap = new AppleTvJoinMap(joinStart); var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); @@ -235,42 +245,6 @@ namespace PepperDash.Essentials.Devices.Common trilist.SetBoolSigAction(joinMap.Select.JoinNumber, Select); trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, Menu); trilist.SetBoolSigAction(joinMap.PlayPause.JoinNumber, Play); - } - } - - /// - /// Represents a AppleTVFactory - /// - public class AppleTVFactory : EssentialsDeviceFactory - { - public AppleTVFactory() - { - TypeNames = new List() { "appletv" }; } - - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new AppleTV Device"); - var irCont = IRPortHelper.GetIrOutputPortController(dc); - return new AppleTV(dc.Key, dc.Name, irCont); - } - } - - public static class AppleTvIrCommands - { - - public static string Up = "+"; - public static string Down = "-"; - public static string Left = IROutputStandardCommands.IROut_TRACK_MINUS; - public static string Right = IROutputStandardCommands.IROut_TRACK_PLUS; - public static string Enter = IROutputStandardCommands.IROut_ENTER; - public static string PlayPause = "PLAY/PAUSE"; - public static string Rewind = "REWIND"; - public static string Menu = "Menu"; - public static string FastForward = "FASTFORWARD"; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTVFactory.cs b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTVFactory.cs new file mode 100644 index 00000000..f5ef907b --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTVFactory.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using Serilog.Events; + +namespace PepperDash.Essentials.Devices.Common +{ + /// + /// Represents a AppleTVFactory + /// + public class AppleTVFactory : EssentialsDeviceFactory + { + /// + /// Initializes a new instance of the class + /// + public AppleTVFactory() + { + TypeNames = new List() { "appletv" }; + } + + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new AppleTV Device"); + var irCont = IRPortHelper.GetIrOutputPortController(dc); + return new AppleTV(dc.Key, dc.Name, irCont); + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTvIrCommands.cs b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTvIrCommands.cs new file mode 100644 index 00000000..2b3d1d14 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTvIrCommands.cs @@ -0,0 +1,56 @@ +using Crestron.SimplSharpPro; + +namespace PepperDash.Essentials.Devices.Common +{ + /// + /// Represents AppleTvIrCommands + /// + public static class AppleTvIrCommands + { + + /// + /// Up command + /// + public static string Up = "+"; + + /// + /// Down command + /// + public static string Down = "-"; + + /// + /// Left command + /// + public static string Left = IROutputStandardCommands.IROut_TRACK_MINUS; + + /// + /// Right command + /// + public static string Right = IROutputStandardCommands.IROut_TRACK_PLUS; + + /// + /// Enter command + /// + public static string Enter = IROutputStandardCommands.IROut_ENTER; + + /// + /// PlayPause command + /// + public static string PlayPause = "PLAY/PAUSE"; + + /// + /// Rewind command + /// + public static string Rewind = "REWIND"; + + /// + /// Menu command + /// + public static string Menu = "Menu"; + + /// + /// FastForward command + /// + public static string FastForward = "FASTFORWARD"; + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Streaming/Roku.cs b/src/PepperDash.Essentials.Devices.Common/Streaming/Roku.cs index a08872f5..8b956a5d 100644 --- a/src/PepperDash.Essentials.Devices.Common/Streaming/Roku.cs +++ b/src/PepperDash.Essentials.Devices.Common/Streaming/Roku.cs @@ -1,107 +1,106 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; - -using PepperDash.Core; +using Crestron.SimplSharpPro; using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Config; -using Serilog.Events; namespace PepperDash.Essentials.Devices.Common { - [Description("Wrapper class for an IR-Controlled Roku")] - /// - /// Represents a Roku2 - /// + /// + /// Represents a Roku2 + /// Wrapper class for an IR-Controlled Roku + /// + [Description("Wrapper class for an IR-Controlled Roku")] public class Roku2 : EssentialsDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs { + /// + /// Gets or sets the IrPort + /// [Api] - /// - /// Gets or sets the IrPort - /// public IrOutputPortController IrPort { get; private set; } + + /// + /// Standard Driver Name + /// public const string StandardDriverName = "Roku XD_S.ir"; + /// + /// Gets or sets the DisplayUiType + /// [Api] - /// - /// Gets or sets the DisplayUiType - /// public uint DisplayUiType { get { return DisplayUiConstants.TypeRoku; } } + /// + /// Initializes a new instance of the class + /// public Roku2(string key, string name, IrOutputPortController portCont) : base(key, name) { IrPort = portCont; - DeviceManager.AddDevice(portCont);; + DeviceManager.AddDevice(portCont); ; - HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this); OutputPorts = new RoutingPortCollection { HdmiOut }; } #region IDPad Members + /// + /// Up method + /// [Api] - /// - /// Up method - /// public void Up(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_UP_ARROW, pressRelease); } + /// + /// Down method + /// [Api] - /// - /// Down method - /// public void Down(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_DN_ARROW, pressRelease); } + /// + /// Left method + /// [Api] - /// - /// Left method - /// public void Left(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_LEFT_ARROW, pressRelease); } + /// + /// Right method + /// [Api] - /// - /// Right method - /// public void Right(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_RIGHT_ARROW, pressRelease); } + + /// + /// Select method + /// [Api] - /// - /// Select method - /// public void Select(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_ENTER, pressRelease); } + /// + /// Menu method + /// [Api] - /// - /// Menu method - /// public void Menu(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_MENU, pressRelease); } + /// + /// Exit method + /// [Api] - /// - /// Exit method - /// public void Exit(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_EXIT, pressRelease); @@ -111,49 +110,46 @@ namespace PepperDash.Essentials.Devices.Common #region ITransport Members + /// + /// Play method + /// [Api] - /// - /// Play method - /// public void Play(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_PLAY, pressRelease); } + /// + /// Pause method + /// [Api] - /// - /// Pause method - /// public void Pause(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_PAUSE, pressRelease); } + /// + /// Rewind method + /// [Api] - /// - /// Rewind method - /// public void Rewind(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease); } + /// + /// FFwd method + /// [Api] - /// - /// FFwd method - /// public void FFwd(bool pressRelease) { IrPort.PressRelease(IROutputStandardCommands.IROut_FSCAN, pressRelease); } /// - /// Not implemented + /// ChapMinus method - Not implemented /// /// - /// - /// ChapMinus method - /// public void ChapMinus(bool pressRelease) { } @@ -186,34 +182,18 @@ namespace PepperDash.Essentials.Devices.Common #region IRoutingOutputs Members + /// + /// HdmiOut + /// public RoutingOutputPort HdmiOut { get; private set; } + + /// + /// OutputPorts + /// public RoutingPortCollection OutputPorts { get; private set; } #endregion } - /// - /// Represents a Roku2Factory - /// - public class Roku2Factory : EssentialsDeviceFactory - { - public Roku2Factory() - { - TypeNames = new List() { "roku" }; - } - - /// - /// BuildDevice method - /// - /// - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Roku Device"); - var irCont = IRPortHelper.GetIrOutputPortController(dc); - return new Roku2(dc.Key, dc.Name, irCont); - - } - } - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Streaming/Roku2Factory.cs b/src/PepperDash.Essentials.Devices.Common/Streaming/Roku2Factory.cs new file mode 100644 index 00000000..acd330c4 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/Streaming/Roku2Factory.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using Serilog.Events; + +namespace PepperDash.Essentials.Devices.Common +{ + /// + /// Represents a Roku2Factory + /// + public class Roku2Factory : EssentialsDeviceFactory + { + /// + /// Roku2Factory constructor + /// + public Roku2Factory() + { + TypeNames = new List() { "roku" }; + } + + /// + /// BuildDevice method + /// + /// + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Roku Device"); + var irCont = IRPortHelper.GetIrOutputPortController(dc); + return new Roku2(dc.Key, dc.Name, irCont); + + } + } + +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/CallHistoryDataClasses.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/CallHistoryDataClasses.cs index 9a1f770c..8872172a 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/CallHistoryDataClasses.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/CallHistoryDataClasses.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; namespace PepperDash.Essentials.Devices.Common.VideoCodec { diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/RoomPresets.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/RoomPresets.cs index dfccd74b..e6e2be7e 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/RoomPresets.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/RoomPresets.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; - -using PepperDash.Core; using PepperDash.Essentials.Core.Presets; namespace PepperDash.Essentials.Devices.Common.VideoCodec @@ -38,19 +36,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// /// /// - void CodecRoomPresetStore(int preset, string description); + void CodecRoomPresetStore(int preset, string description); /// /// Selects a far end preset by its ID. This is typically used to recall a preset that has been defined on the far end codec. /// /// - void SelectFarEndPreset(int preset); + void SelectFarEndPreset(int preset); } /// /// Static class for converting non-generic RoomPresets to generic CameraPresets. /// - public static class RoomPresets + public static class RoomPresets { /// /// Converts non-generic RoomPresets to generic CameraPresets diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceMode.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceMode.cs index ef960406..6d77551d 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceMode.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceMode.cs @@ -3,5 +3,23 @@ /// /// Enumeration of eExternalSourceMode values /// - public enum eExternalSourceMode {Ready, NotReady, Hidden, Error} + public enum eExternalSourceMode + { + /// + /// Ready state + /// + Ready, + /// + /// Not ready state + /// + NotReady, + /// + /// Hidden state + /// + Hidden, + /// + /// Error state + /// + Error + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceType.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceType.cs index a5cea36c..6d5811e3 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceType.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceType.cs @@ -3,5 +3,35 @@ /// /// Enumeration of eExternalSourceType values /// - public enum eExternalSourceType {camera, desktop, document_camera, mediaplayer, PC, whiteboard, other} + public enum eExternalSourceType + { + /// + /// Camera source type + /// + camera, + /// + /// Desktop source type + /// + desktop, + /// + /// Document camera source type + /// + document_camera, + /// + /// Media player source type + /// + mediaplayer, + /// + /// PC source type + /// + PC, + /// + /// Whiteboard source type + /// + whiteboard, + /// + /// Other source type + /// + other + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CodecCommandWithLabel.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CodecCommandWithLabel.cs new file mode 100644 index 00000000..a69fc77a --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CodecCommandWithLabel.cs @@ -0,0 +1,31 @@ +namespace PepperDash.Essentials.Devices.Common.VideoCodec +{ + /// + /// Represents a CodecCommandWithLabel + /// + public class CodecCommandWithLabel + { + /// + /// Gets or sets the Command + /// + public string Command { get; private set; } + /// + /// Gets or sets the Label + /// + public string Label { get; private set; } + + /// + /// Constructor for + /// + /// Command string + /// Label string + public CodecCommandWithLabel(string command, string label) + { + Command = command; + Label = label; + } + } + + + +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CodecPhonebookSyncState.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CodecPhonebookSyncState.cs new file mode 100644 index 00000000..c677c906 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CodecPhonebookSyncState.cs @@ -0,0 +1,150 @@ +using System; +using PepperDash.Core; +using Serilog.Events; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec +{ + /// + /// Represents a CodecPhonebookSyncState + /// + public class CodecPhonebookSyncState : IKeyed + { + private bool _InitialSyncComplete; + + /// + /// Constructor for CodecPhonebookSyncState + /// + /// Key for the codec phonebook sync state + public CodecPhonebookSyncState(string key) + { + Key = key; + + CodecDisconnected(); + } + + /// + /// Gets or sets the InitialSyncComplete + /// + public bool InitialSyncComplete + { + get { return _InitialSyncComplete; } + private set + { + if (value == true) + { + InitialSyncCompleted?.Invoke(this, new EventArgs()); + } + _InitialSyncComplete = value; + } + } + + /// + /// Gets or sets the InitialPhonebookFoldersWasReceived + /// + public bool InitialPhonebookFoldersWasReceived { get; private set; } + + /// + /// Gets or sets the NumberOfContactsWasReceived + /// + public bool NumberOfContactsWasReceived { get; private set; } + + /// + /// Gets or sets the PhonebookRootEntriesWasRecieved + /// + public bool PhonebookRootEntriesWasRecieved { get; private set; } + + /// + /// Gets or sets the PhonebookHasFolders + /// + public bool PhonebookHasFolders { get; private set; } + + /// + /// Gets or sets the NumberOfContacts + /// + public int NumberOfContacts { get; private set; } + + #region IKeyed Members + + /// + /// Gets or sets the Key + /// + public string Key { get; private set; } + + #endregion + + /// + /// Event InitialSyncCompleted + /// + public event EventHandler InitialSyncCompleted; + + /// + /// InitialPhonebookFoldersReceived method + /// + public void InitialPhonebookFoldersReceived() + { + InitialPhonebookFoldersWasReceived = true; + + CheckSyncStatus(); + } + + /// + /// PhonebookRootEntriesReceived method + /// + public void PhonebookRootEntriesReceived() + { + PhonebookRootEntriesWasRecieved = true; + + CheckSyncStatus(); + } + + /// + /// SetPhonebookHasFolders method + /// + public void SetPhonebookHasFolders(bool value) + { + PhonebookHasFolders = value; + + Debug.LogMessage(LogEventLevel.Debug, this, "Phonebook has folders: {0}", PhonebookHasFolders); + } + + /// + /// SetNumberOfContacts method + /// + public void SetNumberOfContacts(int contacts) + { + NumberOfContacts = contacts; + NumberOfContactsWasReceived = true; + + Debug.LogMessage(LogEventLevel.Debug, this, "Phonebook contains {0} contacts.", NumberOfContacts); + + CheckSyncStatus(); + } + + /// + /// CodecDisconnected method + /// + public void CodecDisconnected() + { + InitialPhonebookFoldersWasReceived = false; + PhonebookHasFolders = false; + NumberOfContacts = 0; + NumberOfContactsWasReceived = false; + } + + private void CheckSyncStatus() + { + if (InitialPhonebookFoldersWasReceived && NumberOfContactsWasReceived && PhonebookRootEntriesWasRecieved) + { + InitialSyncComplete = true; + Debug.LogMessage(LogEventLevel.Debug, this, "Initial Phonebook Sync Complete!"); + } + else + { + InitialSyncComplete = false; + } + } + } + + + +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ConvertiblePreset.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ConvertiblePreset.cs index 4c01d94e..e75f436d 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ConvertiblePreset.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ConvertiblePreset.cs @@ -2,8 +2,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { + /// + /// Base class for presets that can be converted to PresetBase + /// public abstract class ConvertiblePreset { + /// + /// Converts the preset to a PresetBase + /// + /// public abstract PresetBase ConvertCodecPreset(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/CodecParticipants.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/CodecParticipants.cs new file mode 100644 index 00000000..a297c9e6 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/CodecParticipants.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Represents a CodecParticipants + /// + public class CodecParticipants + { + private List _currentParticipants; + + /// + /// Gets or sets the CurrentParticipants + /// + public List CurrentParticipants + { + get { return _currentParticipants; } + set + { + _currentParticipants = value; + OnParticipantsChanged(); + } + } + + /// + /// Gets the Host participant + /// + public Participant Host + { + get + { + return _currentParticipants.FirstOrDefault(p => p.IsHost); + } + } + + /// + /// Event fired when the participants list has changed + /// + public event EventHandler ParticipantsListHasChanged; + + /// + /// Initializes a new instance of the CodecParticipants class + /// + public CodecParticipants() + { + _currentParticipants = new List(); + } + + /// + /// OnParticipantsChanged method + /// + public void OnParticipantsChanged() + { + var handler = ParticipantsListHasChanged; + + if (handler == null) return; + + handler(this, new EventArgs()); + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index 98a8e4f4..61a40048 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -1,14 +1,4 @@ - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Essentials.Core; - -using Newtonsoft.Json; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.VideoCodec { @@ -17,10 +7,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public interface IHasCodecLayouts { + /// + /// Feedback that indicates the current layout on the local display + /// StringFeedback LocalLayoutFeedback { get; } + /// + /// Toggles the local layout + /// void LocalLayoutToggle(); - void LocalLayoutToggleSingleProminent(); - void MinMaxLayoutToggle(); + + /// + /// Toggles the local layout to single prominent + /// + void LocalLayoutToggleSingleProminent(); + + /// + /// Toggle the MinMax layout + /// + void MinMaxLayoutToggle(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecSelfview.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecSelfview.cs index 3b079b7d..a52670bc 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecSelfview.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecSelfview.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.VideoCodec { @@ -13,14 +7,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public interface IHasCodecSelfView { + /// + /// Feedback that indicates whether Selfview is on + /// BoolFeedback SelfviewIsOnFeedback { get; } + /// + /// Setting that indicates whether the device shows selfview by default + /// bool ShowSelfViewByDefault { get; } + /// + /// Turns selfview on + /// void SelfViewModeOn(); + /// + /// Turns selfview off + /// void SelfViewModeOff(); + /// + /// Toggles selfview mode + /// void SelfViewModeToggle(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index 88ccfcac..6ec1f8da 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -1,12 +1,6 @@  using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using Newtonsoft.Json; namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { @@ -15,94 +9,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces /// public interface IHasMeetingInfo { + /// + /// Raised when meeting info changes + /// event EventHandler MeetingInfoChanged; + /// + /// Gets the current meeting information + /// MeetingInfo MeetingInfo { get; } } - - /// - /// Represents a MeetingInfo - /// - public class MeetingInfo - { - [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] - /// - /// Gets or sets the Id - /// - public string Id { get; private set; } - [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] - public string Name { get; private set; } - [JsonProperty("host", NullValueHandling = NullValueHandling.Ignore)] - public string Host { get; private set; } - [JsonProperty("password", NullValueHandling = NullValueHandling.Ignore)] - public string Password { get; private set; } - [JsonProperty("shareStatus", NullValueHandling = NullValueHandling.Ignore)] - /// - /// Gets or sets the ShareStatus - /// - public string ShareStatus { get; private set; } - [JsonProperty("isHost", NullValueHandling = NullValueHandling.Ignore)] - /// - /// Gets or sets the IsHost - /// - public Boolean IsHost { get; private set; } - [JsonProperty("isSharingMeeting", NullValueHandling = NullValueHandling.Ignore)] - /// - /// Gets or sets the IsSharingMeeting - /// - public Boolean IsSharingMeeting { get; private set; } - [JsonProperty("waitingForHost", NullValueHandling = NullValueHandling.Ignore)] - /// - /// Gets or sets the WaitingForHost - /// - public Boolean WaitingForHost { get; private set; } - [JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)] - /// - /// Gets or sets the IsLocked - /// - public Boolean IsLocked { get; private set; } - [JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)] - /// - /// Gets or sets the IsRecording - /// - public Boolean IsRecording { get; private set; } - [JsonProperty("canRecord", NullValueHandling = NullValueHandling.Ignore)] - /// - /// Gets or sets the CanRecord - /// - public Boolean CanRecord { get; private set; } - - - public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording, bool canRecord) - { - Id = id; - Name = name; - Host = host; - Password = password; - ShareStatus = shareStatus; - IsHost = isHost; - IsSharingMeeting = isSharingMeeting; - WaitingForHost = waitingForHost; - IsLocked = isLocked; - IsRecording = isRecording; - CanRecord = CanRecord; - } - } - - /// - /// Represents a MeetingInfoEventArgs - /// - public class MeetingInfoEventArgs : EventArgs - { - /// - /// Gets or sets the Info - /// - public MeetingInfo Info { get; private set; } - - public MeetingInfoEventArgs(MeetingInfo info) - { - Info = info; - } - - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingLock.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingLock.cs index e7344818..b133eebd 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingLock.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingLock.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { @@ -12,10 +7,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces /// public interface IHasMeetingLock { + /// + /// Feedback that indicates whether the meeting is locked + /// BoolFeedback MeetingIsLockedFeedback { get; } + /// + /// Locks the meeting + /// void LockMeeting(); + + /// + /// Unlocks the meeting + /// void UnLockMeeting(); + + /// + /// Toggles the meeting lock state + /// void ToggleMeetingLock(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecording.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecording.cs index 9946cdd1..96e23daa 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecording.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecording.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { @@ -12,24 +7,24 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces /// public interface IHasMeetingRecording { + /// + /// Feedback that indicates whether the meeting is being recorded + /// BoolFeedback MeetingIsRecordingFeedback { get; } + /// + /// Starts recording the meeting + /// void StartRecording(); - void StopRecording(); - void ToggleRecording(); - } - - /// - /// Defines the contract for IHasMeetingRecordingWithPrompt - /// - public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording - { - BoolFeedback RecordConsentPromptIsVisible { get; } /// - /// Used to agree or disagree to the meeting being recorded when prompted + /// Stops recording the meeting /// - /// - void RecordingPromptAcknowledgement(bool agree); + void StopRecording(); + + /// + /// Toggles recording the meeting + /// + void ToggleRecording(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecordingWithPrompt.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecordingWithPrompt.cs new file mode 100644 index 00000000..13d187c2 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecordingWithPrompt.cs @@ -0,0 +1,21 @@ +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Defines the contract for IHasMeetingRecordingWithPrompt + /// + public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording + { + /// + /// Feedback that indicates whether the recording consent prompt is visible + /// + BoolFeedback RecordConsentPromptIsVisible { get; } + + /// + /// Used to agree or disagree to the meeting being recorded when prompted + /// + /// + void RecordingPromptAcknowledgement(bool agree); + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipantAudioMute.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipantAudioMute.cs new file mode 100644 index 00000000..6ada2e46 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipantAudioMute.cs @@ -0,0 +1,31 @@ +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Defines the contract for IHasParticipantAudioMute + /// + public interface IHasParticipantAudioMute : IHasParticipantVideoMute + { + /// + /// Mute audio of all participants + /// + void MuteAudioForAllParticipants(); + + /// + /// Mute audio for participant + /// + /// The user ID of the participant to mute + void MuteAudioForParticipant(int userId); + + /// + /// Unmute audio for participant + /// + /// The user ID of the participant to unmute + void UnmuteAudioForParticipant(int userId); + + /// + /// Toggles audio for participant + /// + /// The user ID of the participant to toggle + void ToggleAudioForParticipant(int userId); + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipantPinUnpin.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipantPinUnpin.cs new file mode 100644 index 00000000..9167e8a8 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipantPinUnpin.cs @@ -0,0 +1,40 @@ +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Defines the contract for IHasParticipantPinUnpin + /// + public interface IHasParticipantPinUnpin : IHasParticipants + { + /// + /// Feedback that indicates the number of screens available for pinning participants + /// + IntFeedback NumberOfScreensFeedback { get; } + + /// + /// Gets the screen index to pin the user to + /// + int ScreenIndexToPinUserTo { get; } + + /// + /// Pins a participant to a screen + /// + /// The user ID of the participant to pin + /// The screen index to pin the user to + void PinParticipant(int userId, int screenIndex); + + /// + /// Unpins a participant + /// + /// The user ID of the participant to unpin + void UnPinParticipant(int userId); + + /// + /// Toggles the pin state of a participant + /// + /// The user ID of the participant to toggle + /// The screen index to pin the user to + void ToggleParticipantPinState(int userId, int screenIndex); + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipantVideoMute.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipantVideoMute.cs new file mode 100644 index 00000000..3e673cff --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipantVideoMute.cs @@ -0,0 +1,26 @@ +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Describes the ability to mute and unmute a participant's video in a meeting + /// + public interface IHasParticipantVideoMute : IHasParticipants + { + /// + /// Mute video of all participants + /// + /// The user ID of the participant to mute + void MuteVideoForParticipant(int userId); + + /// + /// Unmute video of all participants + /// + /// The user ID of the participant to unmute + void UnmuteVideoForParticipant(int userId); + + /// + /// Toggles video of a participant + /// + /// The user ID of the participant to toggle + void ToggleVideoForParticipant(int userId); + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipants.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipants.cs index 0f89eb91..6ff549af 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipants.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipants.cs @@ -1,156 +1,31 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using PepperDash.Core; -using PepperDash.Essentials.Core; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { /// /// Describes a device that has call participants /// public interface IHasParticipants { + /// + /// Gets the collection of participants + /// CodecParticipants Participants { get; } - /// - /// Removes the participant from the meeting - /// - /// - void RemoveParticipant(int userId); + /// + /// Removes the participant from the meeting + /// + /// + void RemoveParticipant(int userId); - /// - /// Sets the participant as the new host - /// - /// - void SetParticipantAsHost(int userId); + /// + /// Sets the participant as the new host + /// + /// + void SetParticipantAsHost(int userId); - /// - /// Admits a participant from the waiting room - /// - /// - void AdmitParticipantFromWaitingRoom(int userId); - } - - /// - /// Describes the ability to mute and unmute a participant's video in a meeting - /// - public interface IHasParticipantVideoMute : IHasParticipants - { - void MuteVideoForParticipant(int userId); - void UnmuteVideoForParticipant(int userId); - void ToggleVideoForParticipant(int userId); - } - - /// - /// Defines the contract for IHasParticipantAudioMute - /// - public interface IHasParticipantAudioMute : IHasParticipantVideoMute - { - /// - /// Mute audio of all participants - /// - void MuteAudioForAllParticipants(); - - void MuteAudioForParticipant(int userId); - void UnmuteAudioForParticipant(int userId); - void ToggleAudioForParticipant(int userId); - } - - /// - /// Defines the contract for IHasParticipantPinUnpin - /// - public interface IHasParticipantPinUnpin : IHasParticipants - { - IntFeedback NumberOfScreensFeedback { get; } - int ScreenIndexToPinUserTo { get; } - - void PinParticipant(int userId, int screenIndex); - void UnPinParticipant(int userId); - void ToggleParticipantPinState(int userId, int screenIndex); - } - - /// - /// Represents a CodecParticipants - /// - public class CodecParticipants - { - private List _currentParticipants; - - public List CurrentParticipants - { - get { return _currentParticipants; } - set - { - _currentParticipants = value; - OnParticipantsChanged(); - } - } - - public Participant Host - { - get - { - return _currentParticipants.FirstOrDefault(p => p.IsHost); - } - } - - public event EventHandler ParticipantsListHasChanged; - - public CodecParticipants() - { - _currentParticipants = new List(); - } - - /// - /// OnParticipantsChanged method - /// - public void OnParticipantsChanged() - { - var handler = ParticipantsListHasChanged; - - if (handler == null) return; - - handler(this, new EventArgs()); - } - } - - /// - /// Represents a Participant - /// - public class Participant - { - /// - /// Gets or sets the UserId - /// - public int UserId { get; set; } - /// - /// Gets or sets the IsHost - /// - public bool IsHost { get; set; } - public bool IsMyself { get; set; } - public string Name { get; set; } - public bool CanMuteVideo { get; set; } - public bool CanUnmuteVideo { get; set; } - public bool VideoMuteFb { get; set; } - public bool AudioMuteFb { get; set; } - /// - /// Gets or sets the HandIsRaisedFb - /// - public bool HandIsRaisedFb { get; set; } - /// - /// Gets or sets the IsPinnedFb - /// - public bool IsPinnedFb { get; set; } - /// - /// Gets or sets the ScreenIndexIsPinnedToFb - /// - public int ScreenIndexIsPinnedToFb { get; set; } - - public Participant() - { - // Initialize to -1 (no screen) - ScreenIndexIsPinnedToFb = -1; - } + /// + /// Admits a participant from the waiting room + /// + /// + void AdmitParticipantFromWaitingRoom(int userId); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs index cb52efc2..b2180c39 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs @@ -5,10 +5,35 @@ /// public interface IHasPresentationOnlyMeeting { + /// + /// Starts a presentation only meeting + /// void StartSharingOnlyMeeting(); + + /// + /// Starts a presentation only meeting with specified display mode + /// + /// The display mode for the meeting void StartSharingOnlyMeeting(eSharingMeetingMode displayMode); + + /// + /// Starts a presentation only meeting with specified display mode and duration + /// + /// The display mode for the meeting + /// The duration for the meeting void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration); + + /// + /// Starts a presentation only meeting with specified display mode, duration, and password + /// + /// The display mode for the meeting + /// The duration for the meeting + /// The password for the meeting void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration, string password); + + /// + /// Starts a normal meeting from a sharing only meeting + /// void StartNormalMeetingFromSharingOnlyMeeting(); } @@ -17,8 +42,17 @@ /// public enum eSharingMeetingMode { + /// + /// No specific sharing mode + /// None, + /// + /// Laptop sharing mode + /// Laptop, + /// + /// iOS sharing mode + /// Ios, } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs index dbb6d0ef..46c3d8f7 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs @@ -1,5 +1,4 @@ -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Devices.Common.VideoCodec; +using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Core.DeviceTypeInterfaces { @@ -8,10 +7,19 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces /// public interface IHasSelfviewPosition { + /// + /// Gets the SelfviewPipPositionFeedback + /// StringFeedback SelfviewPipPositionFeedback { get; } + /// + /// Sets the selfview position + /// void SelfviewPipPositionSet(CodecCommandWithLabel position); + /// + /// Toggles the selfview position + /// void SelfviewPipPositionToggle(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewSize.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewSize.cs index 45365ce1..ab08a414 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewSize.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewSize.cs @@ -2,15 +2,25 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces { - /// - /// Defines the contract for IHasSelfviewSize - /// + /// + /// Defines the contract for IHasSelfviewSize + /// public interface IHasSelfviewSize { + /// + /// Gets the SelfviewPipSizeFeedback + /// StringFeedback SelfviewPipSizeFeedback { get; } + /// + /// Sets the selfview size + /// + /// The new selfview size void SelfviewPipSizeSet(CodecCommandWithLabel size); + /// + /// Toggles the selfview size + /// void SelfviewPipSizeToggle(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStandbyMode.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStandbyMode.cs index 6b2ebe38..d0f1333b 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStandbyMode.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStandbyMode.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.VideoCodec { @@ -13,10 +7,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public interface IHasStandbyMode { + /// + /// Feedback that indicates whether Standby Mode is on + /// BoolFeedback StandbyIsOnFeedback { get; } + /// + /// Activates Standby Mode + /// void StandbyActivate(); + /// + /// Deactivates Standby Mode + /// void StandbyDeactivate(); } @@ -25,10 +28,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public interface IHasHalfWakeMode : IHasStandbyMode { + /// + /// Feedback that indicates whether Half Wake Mode is on + /// BoolFeedback HalfWakeModeIsOnFeedback { get; } + /// + /// Feedback that indicates whether the device is entering Standby Mode + /// BoolFeedback EnteringStandbyModeFeedback { get; } + /// + /// Activates Half Wake Mode + /// void HalfwakeActivate(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStartMeeting.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStartMeeting.cs index 6af59534..357416e2 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStartMeeting.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStartMeeting.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces { /// /// Describes the ability to start an ad-hoc meeting diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasVideoCodec.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasVideoCodec.cs index f7b8f9ad..cdeb9190 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasVideoCodec.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasVideoCodec.cs @@ -1,25 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Devices.Common.VideoCodec { /// /// For rooms that have video codec /// - public interface IHasVideoCodec:IHasInCallFeedback,IPrivacy + public interface IHasVideoCodec : IHasInCallFeedback, IPrivacy { + /// + /// Gets the VideoCodecBase instance + /// VideoCodecBase VideoCodec { get; } - /// - /// Make this more specific - /// - //List ActiveCalls { get; } - /// /// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis /// diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IJoinCalls.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IJoinCalls.cs index 25a807a1..b2583a5d 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IJoinCalls.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IJoinCalls.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Essentials.Devices.Common.Codec; +using PepperDash.Essentials.Devices.Common.Codec; namespace PepperDash.Essentials.Devices.Common.VideoCodec { @@ -13,7 +7,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public interface IJoinCalls { + /// + /// Joins a call + /// + /// The active call to join void JoinCall(CodecActiveCallItem activeCall); + + /// + /// Joins all calls + /// void JoinAllCalls(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/MeetingInfo.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/MeetingInfo.cs new file mode 100644 index 00000000..a65b6830 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/MeetingInfo.cs @@ -0,0 +1,106 @@ +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Represents a MeetingInfo + /// + public class MeetingInfo + { + + /// + /// Gets or sets the Id + /// + [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] + public string Id { get; private set; } + + /// + /// Gets or sets the Name + /// + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public string Name { get; private set; } + + /// + /// Gets or sets the Host + /// + [JsonProperty("host", NullValueHandling = NullValueHandling.Ignore)] + public string Host { get; private set; } + + /// + /// Gets or sets the Password + /// + [JsonProperty("password", NullValueHandling = NullValueHandling.Ignore)] + public string Password { get; private set; } + + /// + /// Gets or sets the ShareStatus + /// + [JsonProperty("shareStatus", NullValueHandling = NullValueHandling.Ignore)] + public string ShareStatus { get; private set; } + + /// + /// Gets or sets the IsHost + /// + [JsonProperty("isHost", NullValueHandling = NullValueHandling.Ignore)] + public bool IsHost { get; private set; } + + /// + /// Gets or sets the IsSharingMeeting + /// + [JsonProperty("isSharingMeeting", NullValueHandling = NullValueHandling.Ignore)] + public bool IsSharingMeeting { get; private set; } + + /// + /// Gets or sets the WaitingForHost + /// + [JsonProperty("waitingForHost", NullValueHandling = NullValueHandling.Ignore)] + public bool WaitingForHost { get; private set; } + + /// + /// Gets or sets the IsLocked + /// + [JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)] + public bool IsLocked { get; private set; } + + /// + /// Gets or sets the IsRecording + /// + [JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)] + public bool IsRecording { get; private set; } + + /// + /// Gets or sets the CanRecord + /// + [JsonProperty("canRecord", NullValueHandling = NullValueHandling.Ignore)] + public bool CanRecord { get; private set; } + + /// + /// Constructor for MeetingInfo + /// + /// The unique identifier for the meeting + /// The name of the meeting + /// The host of the meeting + /// The password for the meeting + /// The share status of the meeting + /// Indicates whether the current user is the host + /// Indicates whether the meeting is currently being shared + /// Indicates whether the meeting is waiting for the host to join + /// Indicates whether the meeting is locked + /// Indicates whether the meeting is being recorded + /// Indicates whether the meeting can be recorded + public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording, bool canRecord) + { + Id = id; + Name = name; + Host = host; + Password = password; + ShareStatus = shareStatus; + IsHost = isHost; + IsSharingMeeting = isSharingMeeting; + WaitingForHost = waitingForHost; + IsLocked = isLocked; + IsRecording = isRecording; + CanRecord = CanRecord; + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/MeetingInfoEventArgs.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/MeetingInfoEventArgs.cs new file mode 100644 index 00000000..f483a564 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/MeetingInfoEventArgs.cs @@ -0,0 +1,27 @@ + + +using System; + +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Represents a MeetingInfoEventArgs + /// + public class MeetingInfoEventArgs : EventArgs + { + /// + /// Gets or sets the Info + /// + public MeetingInfo Info { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The meeting information. + public MeetingInfoEventArgs(MeetingInfo info) + { + Info = info; + } + + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/Participant.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/Participant.cs new file mode 100644 index 00000000..2d266a95 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/Participant.cs @@ -0,0 +1,72 @@ +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +{ + /// + /// Represents a Participant + /// + public class Participant + { + /// + /// Gets or sets the UserId + /// + public int UserId { get; set; } + + /// + /// Gets or sets the IsHost + /// + public bool IsHost { get; set; } + + /// + /// Gets or sets the IsMyself + /// + public bool IsMyself { get; set; } + + /// + /// Gets or sets the Name + /// + public string Name { get; set; } + + /// + /// Gets or sets the Email + /// + public bool CanMuteVideo { get; set; } + + /// + /// Gets or sets the CanUnmuteVideo + /// + public bool CanUnmuteVideo { get; set; } + + /// + /// Gets or sets the CanMuteAudio + /// + public bool VideoMuteFb { get; set; } + + /// + /// Gets or sets the AudioMuteFb + /// + public bool AudioMuteFb { get; set; } + + /// + /// Gets or sets the HandIsRaisedFb + /// + public bool HandIsRaisedFb { get; set; } + + /// + /// Gets or sets the IsPinnedFb + /// + public bool IsPinnedFb { get; set; } + + /// + /// Gets or sets the ScreenIndexIsPinnedToFb + /// + public int ScreenIndexIsPinnedToFb { get; set; } + + /// + /// Initializes a new instance of the class + /// + public Participant() + { + // Initialize to -1 (no screen) + ScreenIndexIsPinnedToFb = -1; + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/iVideoCodecInfo.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/iVideoCodecInfo.cs index 8f004086..8b1be9e9 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/iVideoCodecInfo.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/iVideoCodecInfo.cs @@ -1,12 +1,4 @@ - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using Newtonsoft.Json; +using Newtonsoft.Json; namespace PepperDash.Essentials.Devices.Common.Codec { @@ -15,6 +7,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public interface iVideoCodecInfo { + /// + /// Gets the codec information + /// VideoCodecInfo CodecInfo { get; } } @@ -23,18 +18,39 @@ namespace PepperDash.Essentials.Devices.Common.Codec /// public abstract class VideoCodecInfo { + /// + /// Gets a value indicating whether the multi-site option is enabled + /// [JsonProperty("multiSiteOptionIsEnabled", NullValueHandling = NullValueHandling.Ignore)] public abstract bool MultiSiteOptionIsEnabled { get; } + /// + /// Gets the IP address of the codec + /// [JsonProperty("ipAddress", NullValueHandling = NullValueHandling.Ignore)] public abstract string IpAddress { get; } + /// + /// Gets the SIP phone number for the codec + /// [JsonProperty("sipPhoneNumber", NullValueHandling = NullValueHandling.Ignore)] public abstract string SipPhoneNumber { get; } + /// + /// Gets the E164 alias for the codec + /// [JsonProperty("e164Alias", NullValueHandling = NullValueHandling.Ignore)] public abstract string E164Alias { get; } + /// + /// Gets the H323 ID for the codec + /// [JsonProperty("h323Id", NullValueHandling = NullValueHandling.Ignore)] public abstract string H323Id { get; } + /// + /// Gets the SIP URI for the codec + /// [JsonProperty("sipUri", NullValueHandling = NullValueHandling.Ignore)] public abstract string SipUri { get; } + /// + /// Gets a value indicating whether auto-answer is enabled + /// [JsonProperty("autoAnswerEnabled", NullValueHandling = NullValueHandling.Ignore)] public abstract bool AutoAnswerEnabled { get; } } diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockCodecDirectory.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockCodecDirectory.cs index 9b9aa8d7..185f089f 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockCodecDirectory.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockCodecDirectory.cs @@ -1,16 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Core; -using PepperDash.Essentials.Core; +using System.Collections.Generic; using PepperDash.Essentials.Devices.Common.Codec; namespace PepperDash.Essentials.Devices.Common.VideoCodec { + /// + /// Mock video codec directory structure + /// public static class MockVideoCodecDirectory { /// @@ -18,13 +14,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public enum eFolderId { + /// + /// The United States folder + /// UnitedStates, + /// + /// The Canada folder + /// Canada, + /// + /// The New York folder + /// NewYork, + /// + /// The Boston folder + /// Boston, + /// + /// The San Francisco folder + /// SanFrancisco, + /// + /// The Denver folder + /// Denver, + /// + /// The Austin folder + /// Austin, + /// + /// The Calgary folder + /// Calgary } @@ -51,16 +71,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } - public static CodecDirectory DirectoryRoot + /// + /// The root of the directory structure + /// + public static CodecDirectory DirectoryRoot { get { var directory = new CodecDirectory(); - + directory.AddFoldersToDirectory - ( + ( new List() - { + { new DirectoryFolder() { FolderId = eFolderId.UnitedStates.ToString(), @@ -77,7 +100,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } ); - + directory.AddContactsToDirectory ( new List() @@ -97,23 +120,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } } - ); - + ); + return directory; - } + } } + /// + /// Contents of the United States folder + /// public static CodecDirectory UnitedStatesFolderContents { get { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.UnitedStates.ToString(); - directory.AddFoldersToDirectory - ( - new List() - { + var directory = new CodecDirectory + { + ResultsFolderId = eFolderId.UnitedStates.ToString() + }; + directory.AddFoldersToDirectory + ( + new List() + { new DirectoryFolder() { FolderId = eFolderId.NewYork.ToString(), @@ -149,24 +176,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec ParentFolderId = eFolderId.UnitedStates.ToString(), Contacts = null } - } - ); + } + ); return directory; } } + /// + /// Contents of the New York folder + /// public static CodecDirectory NewYorkFolderContents { get { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.NewYork.ToString(); + var directory = new CodecDirectory + { + ResultsFolderId = eFolderId.NewYork.ToString() + }; directory.AddContactsToDirectory - ( - new List() - { + ( + new List() + { new DirectoryContact() { ContactId = "nyc_1", @@ -215,24 +246,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } } - } - ); + } + ); return directory; } } + /// + /// Contents of the Boston folder + /// public static CodecDirectory BostonFolderContents { get { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Boston.ToString(); + var directory = new CodecDirectory + { + ResultsFolderId = eFolderId.Boston.ToString() + }; directory.AddContactsToDirectory - ( - new List() - { + ( + new List() + { new DirectoryContact() { ContactId = "bos_1", @@ -249,24 +284,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } } - } - ); + } + ); return directory; } } + /// + /// Contents of the San Francisco folder + /// public static CodecDirectory SanFranciscoFolderContents { get { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.SanFrancisco.ToString(); + var directory = new CodecDirectory + { + ResultsFolderId = eFolderId.SanFrancisco.ToString() + }; directory.AddContactsToDirectory - ( - new List() - { + ( + new List() + { new DirectoryContact() { ContactId = "sfo_1", @@ -282,25 +321,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec CallType = eContactMethodCallType.Video } } - } - } - ); + } + } + ); return directory; } } + /// + /// Contents of the Denver folder + /// public static CodecDirectory DenverFolderContents { get { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Denver.ToString(); + var directory = new CodecDirectory + { + ResultsFolderId = eFolderId.Denver.ToString() + }; directory.AddContactsToDirectory - ( - new List() - { + ( + new List() + { new DirectoryContact() { ContactId = "den_1", @@ -316,25 +359,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec CallType = eContactMethodCallType.Video } } - } - } - ); + } + } + ); return directory; } } + /// + /// Contents of the Austin folder + /// public static CodecDirectory AustinFolderContents { get { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Austin.ToString(); + var directory = new CodecDirectory + { + ResultsFolderId = eFolderId.Austin.ToString() + }; directory.AddContactsToDirectory - ( - new List() - { + ( + new List() + { new DirectoryContact() { ContactId = "atx_1", @@ -350,25 +397,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec CallType = eContactMethodCallType.Video } } - } - } - ); + } + } + ); return directory; } } + /// + /// Contents of the Canada folder + /// public static CodecDirectory CanadaFolderContents { get { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Canada.ToString(); + var directory = new CodecDirectory + { + ResultsFolderId = eFolderId.Canada.ToString() + }; directory.AddFoldersToDirectory - ( - new List() - { + ( + new List() + { new DirectoryFolder() { FolderId = eFolderId.Calgary.ToString(), @@ -376,24 +427,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec ParentFolderId = eFolderId.Canada.ToString(), Contacts = null } - } - ); + } + ); return directory; } } + /// + /// Contents of the Calgary folder + /// public static CodecDirectory CalgaryFolderContents { get { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Calgary.ToString(); + var directory = new CodecDirectory + { + ResultsFolderId = eFolderId.Calgary.ToString() + }; directory.AddContactsToDirectory - ( - new List() - { + ( + new List() + { new DirectoryContact() { ContactId = "cdn_1", @@ -409,14 +464,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec CallType = eContactMethodCallType.Video } } - } - } - ); + } + } + ); return directory; } } - - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs index 0387c416..e9f7908c 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs @@ -3,19 +3,17 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro.DeviceSupport; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Routing; -using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.Cameras; - -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using PepperDash.Essentials.Devices.Common.Codec; using Serilog.Events; namespace PepperDash.Essentials.Devices.Common.VideoCodec @@ -47,10 +45,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public RoutingOutputPort HdmiOut { get; private set; } - /// - /// Gets or sets the CallFavorites - /// - public CodecCallFavorites CallFavorites { get; private set; } + /// + /// Gets or sets the CallFavorites + /// + public CodecCallFavorites CallFavorites { get; private set; } /// /// @@ -62,22 +60,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec CodecInfo = new MockCodecInfo(); - // Get favoritesw + // Get favoritesw if (PropertiesConfig.Favorites != null) - { - CallFavorites = new CodecCallFavorites(); - CallFavorites.Favorites = PropertiesConfig.Favorites; - } + { + CallFavorites = new CodecCallFavorites(); + CallFavorites.Favorites = PropertiesConfig.Favorites; + } DirectoryBrowseHistory = new List(); // Debug helpers MuteFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "Mute={0}", _IsMuted); PrivacyModeIsOnFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "Privacy={0}", _PrivacyModeIsOn); - SharingSourceFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "SharingSource={0}", _SharingSource); + SharingSourceFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "SharingSource={0}", _SharingSource); VolumeLevelFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "Volume={0}", _VolumeLevel); - CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => DirectoryBrowseHistory.Count > 0); + CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback("currentDirectoryResultIsNotDirectoryRoot", () => DirectoryBrowseHistory.Count > 0); CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); @@ -105,38 +103,44 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec CreateOsdSource(); SetIsReady(); - } + } + /// 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 SharingContentIsOnFeedbackFunc { get { return () => _SharingIsOn; } } bool _SharingIsOn; + /// protected override Func VolumeLevelFeedbackFunc { get { return () => _VolumeLevel; } } int _VolumeLevel; + /// protected override Func StandbyIsOnFeedbackFunc { get { return () => _StandbyIsOn; } @@ -157,9 +161,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //foreach(var input in Status.Video. } - /// - /// Dial method - /// /// public override void Dial(string number) { @@ -177,9 +178,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }, 2000); } - /// - /// Dial method - /// /// public override void Dial(Meeting meeting) { @@ -199,9 +197,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } - /// - /// EndCall method - /// /// public override void EndCall(CodecActiveCallItem call) { @@ -211,14 +206,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //ActiveCallCountFeedback.FireUpdate(); } - /// - /// EndAllCalls method - /// + /// public override void EndAllCalls() { Debug.LogMessage(LogEventLevel.Debug, this, "EndAllCalls"); - for(int i = ActiveCalls.Count - 1; i >= 0; i--) + for (int i = ActiveCalls.Count - 1; i >= 0; i--) { var call = ActiveCalls[i]; ActiveCalls.Remove(call); @@ -227,9 +220,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //ActiveCallCountFeedback.FireUpdate(); } - /// - /// AcceptCall method - /// + /// public override void AcceptCall(CodecActiveCallItem call) { @@ -239,9 +230,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec // should already be in active list } - /// - /// RejectCall method - /// /// public override void RejectCall(CodecActiveCallItem call) { @@ -251,65 +239,44 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //ActiveCallCountFeedback.FireUpdate(); } - /// - /// Makes horrible tones go out on the wire! - /// - /// - /// - /// SendDtmf method - /// + /// public override void SendDtmf(string s) { Debug.LogMessage(LogEventLevel.Debug, this, "SendDTMF: {0}", s); } - /// - /// - /// + /// public override void StartSharing() { _SharingIsOn = true; SharingContentIsOnFeedback.FireUpdate(); } - /// - /// - /// + /// public override void StopSharing() { _SharingIsOn = false; SharingContentIsOnFeedback.FireUpdate(); } + /// public override void StandbyActivate() { _StandbyIsOn = true; } - /// - /// StandbyDeactivate method - /// /// public override void StandbyDeactivate() { _StandbyIsOn = false; } - /// - /// LinkToApi method - /// + /// public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { throw new NotImplementedException(); } - /// - /// Called by routing to make it happen - /// - /// - /// - /// ExecuteSwitch method - /// /// public override void ExecuteSwitch(object selector) { @@ -317,40 +284,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec _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(); } - - /// - /// - /// - /// - /// - /// SetVolume method - /// + /// public override void SetVolume(ushort level) { @@ -358,29 +312,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec VolumeLevelFeedback.FireUpdate(); } - /// - /// - /// - /// - /// - /// VolumeDown method - /// /// public override void VolumeDown(bool pressRelease) { } - /// - /// - /// - /// + + /// public override void VolumeUp(bool pressRelease) { } - /// - /// - /// + /// public override void PrivacyModeOn() { Debug.LogMessage(LogEventLevel.Debug, this, "PrivacyMuteOn"); @@ -390,9 +333,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec PrivacyModeIsOnFeedback.FireUpdate(); } - /// - /// PrivacyModeOff method - /// + /// public override void PrivacyModeOff() { @@ -403,45 +344,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec PrivacyModeIsOnFeedback.FireUpdate(); } - /// - /// PrivacyModeToggle method - /// + /// public override void PrivacyModeToggle() { _PrivacyModeIsOn = !_PrivacyModeIsOn; - Debug.LogMessage(LogEventLevel.Debug, this, "PrivacyMuteToggle: {0}", _PrivacyModeIsOn); - PrivacyModeIsOnFeedback.FireUpdate(); + Debug.LogMessage(LogEventLevel.Debug, this, "PrivacyMuteToggle: {0}", _PrivacyModeIsOn); + PrivacyModeIsOnFeedback.FireUpdate(); } //******************************************************** // SIMULATION METHODS - /// - /// - /// - /// /// /// TestIncomingVideoCall method /// + /// public void TestIncomingVideoCall(string url) { Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingVideoCall from {0}", url); - var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type= eCodecCallType.Video, Direction = eCodecCallDirection.Incoming }; + var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type = eCodecCallType.Video, Direction = eCodecCallDirection.Incoming }; ActiveCalls.Add(call); SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); //OnCallStatusChange(eCodecCallStatus.Unknown, eCodecCallStatus.Ringing, call); - + } - /// - /// - /// - /// /// /// TestIncomingAudioCall method /// + /// public void TestIncomingAudioCall(string url) { Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingAudioCall from {0}", url); @@ -451,7 +384,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //OnCallStatusChange(eCodecCallStatus.Unknown, eCodecCallStatus.Ringing, call); } - + /// /// TestFarEndHangup method /// @@ -464,6 +397,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec #region IHasCallHistory Members + /// + /// CallHistory property + /// public CodecCallHistory CallHistory { get; private set; } /// @@ -471,12 +407,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry) { - + } #endregion - #region IHasScheduleAwareness Members + #region IHasScheduleAwareness Members /// /// GetSchedule method @@ -486,47 +422,59 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } - public CodecScheduleAwareness CodecSchedule - { - get { - // if the last meeting has past, generate a new list - if (_CodecSchedule == null || _CodecSchedule.Meetings.Count == 0 - || _CodecSchedule.Meetings[_CodecSchedule.Meetings.Count - 1].StartTime < DateTime.Now) - { - _CodecSchedule = new CodecScheduleAwareness(1000); - for (int i = 0; i < 5; i++) - { - var m = new Meeting(); + /// + /// CodecSchedule property + /// + public CodecScheduleAwareness CodecSchedule + { + get + { + // if the last meeting has past, generate a new list + if (_CodecSchedule == null || _CodecSchedule.Meetings.Count == 0 + || _CodecSchedule.Meetings[_CodecSchedule.Meetings.Count - 1].StartTime < DateTime.Now) + { + _CodecSchedule = new CodecScheduleAwareness(1000); + for (int i = 0; i < 5; i++) + { + var m = new Meeting(); m.MinutesBeforeMeeting = 5; m.Id = i.ToString(); m.Organizer = "Employee " + 1; - m.StartTime = DateTime.Now.AddMinutes(5).AddHours(i); - m.EndTime = DateTime.Now.AddHours(i).AddMinutes(50); - m.Title = "Meeting " + i; - m.Calls.Add(new Call() { Number = i + "meeting@fake.com"}); - _CodecSchedule.Meetings.Add(m); - } - } - return _CodecSchedule; - } - } - CodecScheduleAwareness _CodecSchedule; + m.StartTime = DateTime.Now.AddMinutes(5).AddHours(i); + m.EndTime = DateTime.Now.AddHours(i).AddMinutes(50); + m.Title = "Meeting " + i; + m.Calls.Add(new Call() { Number = i + "meeting@fake.com" }); + _CodecSchedule.Meetings.Add(m); + } + } + return _CodecSchedule; + } + } + CodecScheduleAwareness _CodecSchedule; - #endregion + #endregion #region IHasDirectory Members + /// + /// DirectoryResultReturned event. Fired when the directory result changes + /// public event EventHandler DirectoryResultReturned; - + /// + /// DirectoryRoot property. The root of the directory + /// public CodecDirectory DirectoryRoot { - get + get { return MockVideoCodecDirectory.DirectoryRoot; } } + /// + /// CurrentDirectoryResult property. The current directory result + /// public CodecDirectory CurrentDirectoryResult { get @@ -538,9 +486,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } + /// + /// PhonebookSyncState property. The current state of the phonebook synchronization + /// public CodecPhonebookSyncState PhonebookSyncState { - get + get { var syncState = new CodecPhonebookSyncState(Key + "PhonebookSync"); @@ -554,8 +505,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } /// - /// SearchDirectory method + /// Search the directory for contacts that contain the search string /// + /// The search string to use public void SearchDirectory(string searchString) { var searchResults = new CodecDirectory(); @@ -577,8 +529,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } /// - /// GetDirectoryFolderContents method + /// Get the contents of the specified folder /// + /// The ID of the folder to get the contents of public void GetDirectoryFolderContents(string folderId) { var folderDirectory = new CodecDirectory(); @@ -606,7 +559,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } /// - /// SetCurrentDirectoryToRoot method + /// Set the current directory to the root /// public void SetCurrentDirectoryToRoot() { @@ -616,7 +569,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } /// - /// GetDirectoryParentFolderContents method + /// Get the contents of the parent folder /// public void GetDirectoryParentFolderContents() { @@ -656,16 +609,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public void OnDirectoryResultReturned(CodecDirectory result) { CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); - - var handler = DirectoryResultReturned; - if (handler != null) + DirectoryResultReturned?.Invoke(this, new DirectoryEventArgs() { - handler(this, new DirectoryEventArgs() - { - Directory = result, - DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue - }); - } + Directory = result, + DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue + }); } #endregion @@ -686,11 +634,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec Cameras.Add(farEndCamera); - SelectedCameraFeedback = new StringFeedback(() => SelectedCamera.Key); + SelectedCameraFeedback = new StringFeedback("selectedCamera", () => SelectedCamera.Key); - ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); + ControllingFarEndCameraFeedback = new BoolFeedback("controllingFarEndCamera", () => SelectedCamera is IAmFarEndCamera); - CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn); + CameraAutoModeIsOnFeedback = new BoolFeedback("cameraAutoModeIsOn", () => _CameraAutoModeIsOn); SupportsCameraAutoMode = true; @@ -728,10 +676,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec #region IHasCameras Members + /// + /// CameraSelected event. Fired when a camera is selected + /// public event EventHandler CameraSelected; /// - /// Gets or sets the Cameras + /// Gets the list of cameras associated with this codec /// public List Cameras { get; private set; } @@ -751,12 +702,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec _selectedCamera = value; SelectedCameraFeedback.FireUpdate(); ControllingFarEndCameraFeedback.FireUpdate(); - - var handler = CameraSelected; - if (handler != null) - { - handler(this, new CameraSelectedEventArgs(SelectedCamera)); - } + CameraSelected?.Invoke(this, new CameraSelectedEventArgs(SelectedCamera)); } } @@ -788,7 +734,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// Gets or sets the FarEndCamera /// public CameraBase FarEndCamera { get; private set; } - + /// /// Gets or sets the ControllingFarEndCameraFeedback /// @@ -823,7 +769,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public void CameraAutoModeToggle() { - if(_CameraAutoModeIsOn) + if (_CameraAutoModeIsOn) _CameraAutoModeIsOn = false; else _CameraAutoModeIsOn = true; @@ -835,12 +781,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// /// Gets or sets the CameraAutoModeIsOnFeedback /// - public BoolFeedback CameraAutoModeIsOnFeedback {get; private set;} + public BoolFeedback CameraAutoModeIsOnFeedback { get; private set; } #endregion #region IHasCameraPresets Members + /// + /// CodecRoomPresetsListHasChanged event. Fired when the presets list changes + /// public event EventHandler CodecRoomPresetsListHasChanged; /// @@ -883,11 +832,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec else NearEndPresets.Add(new CodecRoomPreset(preset, description, true, true)); - var handler = CodecRoomPresetsListHasChanged; - if (handler != null) - { - handler(this, new EventArgs()); - } + CodecRoomPresetsListHasChanged?.Invoke(this, new EventArgs()); // Update the config SetConfig(Config); @@ -903,6 +848,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec #endregion + /// protected override void CustomSetConfig(DeviceConfig config) { PropertiesConfig.Presets = NearEndPresets; @@ -920,11 +866,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec public class MockCodecInfo : VideoCodecInfo { + /// public override bool MultiSiteOptionIsEnabled { get { return true; } } + /// public override string E164Alias { get { return "someE164alias"; } @@ -975,14 +923,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public class MockVCFactory : EssentialsDeviceFactory { + /// public MockVCFactory() { TypeNames = new List() { "mockvc" }; } - /// - /// BuildDevice method - /// /// public override EssentialsDevice BuildDevice(DeviceConfig dc) { diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVCCamera.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVCCamera.cs index 8b39e457..5c7e89d8 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVCCamera.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVCCamera.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Devices.Common.VideoCodec; @@ -16,9 +11,17 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public class MockVCCamera : CameraBase, IHasCameraPtzControl, IHasCameraFocusControl, IBridgeAdvanced { + /// + /// Gets the parent video codec + /// protected VideoCodecBase ParentCodec { get; private set; } - + /// + /// Initializes a new instance of the MockVCCamera class + /// + /// The device key + /// The device name + /// The parent video codec public MockVCCamera(string key, string name, VideoCodecBase codec) : base(key, name) { @@ -173,9 +176,17 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public class MockFarEndVCCamera : CameraBase, IHasCameraPtzControl, IAmFarEndCamera, IBridgeAdvanced { + /// + /// Gets the parent video codec + /// protected VideoCodecBase ParentCodec { get; private set; } - + /// + /// Initializes a new instance of the MockFarEndVCCamera class + /// + /// The device key + /// The device name + /// The parent video codec public MockFarEndVCCamera(string key, string name, VideoCodecBase codec) : base(key, name) { diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs index c34053fc..0c5654d6 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs @@ -1,14 +1,5 @@ - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; +using System.Collections.Generic; using Newtonsoft.Json; - -using PepperDash.Core; -using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.Codec; namespace PepperDash.Essentials.Devices.Common.VideoCodec @@ -18,18 +9,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec /// public class MockVcPropertiesConfig { - [JsonProperty("favorites")] /// /// Gets or sets the Favorites /// + [JsonProperty("favorites")] public List Favorites { get; set; } - [JsonProperty("presets")] /// /// Gets or sets the Presets /// + [JsonProperty("presets")] public List Presets { get; set; } + /// + /// Initializes a new instance of the class. + /// public MockVcPropertiesConfig() { Favorites = new List(); diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs index 8de3afa5..b0b5ef55 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs @@ -1,57 +1,68 @@ using System; using System.Collections.Generic; using System.Linq; -using Crestron.SimplSharp.CrestronIO; -using Crestron.SimplSharp.Reflection; -using Crestron.SimplSharpPro.DeviceSupport; +using System.Text; using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Core.Intersystem; using PepperDash.Core.Intersystem.Tokens; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Bridges.JoinMaps; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Devices; using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; -using PepperDash.Essentials.Core.Bridges.JoinMaps; -using Feedback = PepperDash.Essentials.Core.Feedback; using Serilog.Events; -using PepperDash.Essentials.Core.Routing; -using System.Text; +using Feedback = PepperDash.Essentials.Core.Feedback; namespace PepperDash.Essentials.Devices.Common.VideoCodec { + /// + /// Base class for video codec devices + /// public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs, IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced, IHasStandbyMode { private const int XSigEncoding = 28591; - protected const int MaxParticipants = 50; + + /// + /// Maximum number of participants + /// + protected const int MaxParticipants = 50; private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs(); - private readonly IHasDirectory _directoryCodec; - private readonly BasicTriList _directoryTrilist; - private readonly VideoCodecControllerJoinMap _directoryJoinmap; - - protected string _timeFormatSpecifier; - protected string _dateFormatSpecifier; + /// + /// Time format specifier + /// + protected string _timeFormatSpecifier; + /// + /// Date format specifier + /// + protected string _dateFormatSpecifier; + /// + /// Initializes a new instance of the class. + /// protected VideoCodecBase(DeviceConfig config) : base(config) { - StandbyIsOnFeedback = new BoolFeedback(StandbyIsOnFeedbackFunc); - PrivacyModeIsOnFeedback = new BoolFeedback(PrivacyModeIsOnFeedbackFunc); - VolumeLevelFeedback = new IntFeedback(VolumeLevelFeedbackFunc); - MuteFeedback = new BoolFeedback(MuteFeedbackFunc); - SharingSourceFeedback = new StringFeedback(SharingSourceFeedbackFunc); - SharingContentIsOnFeedback = new BoolFeedback(SharingContentIsOnFeedbackFunc); + StandbyIsOnFeedback = new BoolFeedback("standbyIsOn", StandbyIsOnFeedbackFunc); + PrivacyModeIsOnFeedback = new BoolFeedback("privacyModeIsOn", PrivacyModeIsOnFeedbackFunc); + VolumeLevelFeedback = new IntFeedback("volumeLevel", VolumeLevelFeedbackFunc); + MuteFeedback = new BoolFeedback("mute", MuteFeedbackFunc); + SharingSourceFeedback = new StringFeedback("sharingSource", SharingSourceFeedbackFunc); + SharingContentIsOnFeedback = new BoolFeedback("sharingContentIsOn", SharingContentIsOnFeedbackFunc); - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - MeetingsToDisplayFeedback = new IntFeedback(() => MeetingsToDisplay); + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + MeetingsToDisplayFeedback = new IntFeedback("meetingsToDisplay", () => MeetingsToDisplay); InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); @@ -59,115 +70,177 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec ActiveCalls = new List(); } - /// - /// Gets or sets the Communication - /// + /// + /// Gets or sets the Communication + /// public IBasicCommunication Communication { get; protected set; } - /// - /// Gets or sets the OsdSource - /// + /// + /// Gets or sets the OsdSource + /// public DummyRoutingInputsDevice OsdSource { get; protected set; } - /// - /// Gets or sets the StandbyIsOnFeedback - /// + /// + /// Gets or sets the StandbyIsOnFeedback + /// public BoolFeedback StandbyIsOnFeedback { get; private set; } + /// + /// Gets or sets the PrivacyModeIsOnFeedbackFunc + /// protected abstract Func PrivacyModeIsOnFeedbackFunc { get; } + + /// + /// Gets or sets the VolumeLevelFeedbackFunc + /// protected abstract Func VolumeLevelFeedbackFunc { get; } + + /// + /// Gets or sets the MuteFeedbackFunc + /// protected abstract Func MuteFeedbackFunc { get; } + + /// + /// Gets or sets the StandbyIsOnFeedbackFunc + /// protected abstract Func StandbyIsOnFeedbackFunc { get; } + /// + /// Gets or sets the ActiveCalls + /// public List ActiveCalls { get; set; } - /// - /// Gets or sets the ShowSelfViewByDefault - /// + /// + /// Gets or sets the ShowSelfViewByDefault + /// public bool ShowSelfViewByDefault { get; protected set; } - /// - /// Gets or sets the SupportsCameraOff - /// - public bool SupportsCameraOff { get; protected set; } - /// - /// Gets or sets the SupportsCameraAutoMode - /// - public bool SupportsCameraAutoMode { get; protected set; } + /// + /// Gets or sets the SupportsCameraOff + /// + public bool SupportsCameraOff { get; protected set; } + /// + /// Gets or sets the SupportsCameraAutoMode + /// + public bool SupportsCameraAutoMode { get; protected set; } - /// - /// Gets or sets the IsReady - /// + /// + /// Gets or sets the IsReady + /// public bool IsReady { get; protected set; } + /// public virtual List Feedbacks { get { return new List - { - PrivacyModeIsOnFeedback, - SharingSourceFeedback - }; + { + PrivacyModeIsOnFeedback, + SharingSourceFeedback + }; } } + /// + /// Gets or sets the MeetingsToDisplay + /// protected abstract Func SharingSourceFeedbackFunc { get; } + + /// + /// Gets or sets the SharingContentIsOnFeedbackFunc + /// protected abstract Func SharingContentIsOnFeedbackFunc { get; } #region ICodecAudio Members + /// + /// Set Privacy Mode On + /// public abstract void PrivacyModeOn(); + + /// + /// Set Privacy Mode Off + /// public abstract void PrivacyModeOff(); + + /// + /// Toggles the Privacy Mode + /// public abstract void PrivacyModeToggle(); - /// - /// Gets or sets the PrivacyModeIsOnFeedback - /// + + /// + /// Gets or sets the PrivacyModeIsOnFeedback + /// public BoolFeedback PrivacyModeIsOnFeedback { get; private set; } - - /// - /// Gets or sets the MuteFeedback - /// + /// + /// Gets or sets the MuteFeedback + /// public BoolFeedback MuteFeedback { get; private set; } + /// + /// Sets the Mute state to Off + /// public abstract void MuteOff(); + /// + /// Sets the Mute state to On + /// public abstract void MuteOn(); + /// + /// Sets the Volume level + /// public abstract void SetVolume(ushort level); - /// - /// Gets or sets the VolumeLevelFeedback - /// + /// + /// Gets or sets the VolumeLevelFeedback + /// public IntFeedback VolumeLevelFeedback { get; private set; } + /// + /// Toggles the Mute state + /// public abstract void MuteToggle(); + /// + /// Decreases the Volume level + /// public abstract void VolumeDown(bool pressRelease); - + /// + /// Increases the Volume level + /// public abstract void VolumeUp(bool pressRelease); #endregion #region IHasContentSharing Members + /// + /// Starts content sharing + /// public abstract void StartSharing(); + + /// + /// Stops content sharing + /// public abstract void StopSharing(); - /// - /// Gets or sets the AutoShareContentWhileInCall - /// + /// + /// Gets or sets the AutoShareContentWhileInCall + /// public bool AutoShareContentWhileInCall { get; protected set; } - /// - /// Gets or sets the SharingSourceFeedback - /// + /// + /// Gets or sets the SharingSourceFeedback + /// public StringFeedback SharingSourceFeedback { get; private set; } - /// - /// Gets or sets the SharingContentIsOnFeedback - /// + + /// + /// Gets or sets the SharingContentIsOnFeedback + /// public BoolFeedback SharingContentIsOnFeedback { get; private set; } #endregion @@ -191,60 +264,95 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } } + /// + /// Dials the specified number + /// public abstract void Dial(string number); + + /// + /// Ends the specified call + /// public abstract void EndCall(CodecActiveCallItem call); + + /// + /// Ends all active calls + /// public abstract void EndAllCalls(); + + /// + /// Accepts the specified call + /// public abstract void AcceptCall(CodecActiveCallItem call); + + /// + /// Rejects the specified call + /// public abstract void RejectCall(CodecActiveCallItem call); + + /// + /// Sends DTMF tones + /// public abstract void SendDtmf(string s); - /// - /// SendDtmf method - /// - /// - public virtual void SendDtmf(string s, CodecActiveCallItem call) { } + + /// + /// SendDtmf method + /// + public virtual void SendDtmf(string s, CodecActiveCallItem call) { } #endregion #region IRoutingInputsOutputs Members - /// - /// Gets or sets the InputPorts - /// + /// + /// Gets or sets the InputPorts + /// public RoutingPortCollection InputPorts { get; private set; } - /// - /// Gets or sets the OutputPorts - /// + /// + /// Gets or sets the OutputPorts + /// public RoutingPortCollection OutputPorts { get; private set; } #endregion #region IUsageTracking Members - /// - /// Gets or sets the UsageTracker - /// + /// + /// Gets or sets the UsageTracker + /// public UsageTracking UsageTracker { get; set; } #endregion #region iVideoCodecInfo Members + /// + /// Gets the CodecInfo + /// public VideoCodecInfo CodecInfo { get; protected set; } #endregion + /// + /// Fired when the Codec is ready to be used + /// public event EventHandler IsReadyChange; + + /// + /// Dials the specified meeting + /// + /// public abstract void Dial(Meeting meeting); - /// - /// Dial method - /// - /// + /// + /// Dial a contact + /// + /// The contact to dial public virtual void Dial(IInvitableContact contact) { } + /// public abstract void ExecuteSwitch(object selector); /// @@ -258,16 +366,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } /// - /// - /// - /// - /// + /// Sets the previous and new status for the call + /// /// protected virtual void OnCallStatusChange(CodecActiveCallItem item) { - CallStatusChange?.Invoke(this, new CodecCallStatusItemChangeEventArgs(item)); + CallStatusChange?.Invoke(this, new CodecCallStatusItemChangeEventArgs(item)); - PrivacyModeIsOnFeedback.FireUpdate(); + PrivacyModeIsOnFeedback.FireUpdate(); if (AutoShareContentWhileInCall) { @@ -297,8 +403,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec try { IsReady = true; - IsReadyChange?.Invoke(this, new EventArgs()); - } + IsReadyChange?.Invoke(this, new EventArgs()); + } catch (Exception e) { Debug.LogMessage(LogEventLevel.Verbose, this, "Error in SetIsReady() : {0}", e); @@ -307,13 +413,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } // **** DEBUGGING THINGS **** - /// - /// ListCalls method - /// - /// + /// + /// ListCalls method + /// public virtual void ListCalls() { - Debug.LogMessage(LogEventLevel.Debug, this, "Active Calls:"); + Debug.LogMessage(LogEventLevel.Debug, this, "Active Calls:"); var sb = new StringBuilder(); foreach (var c in ActiveCalls) @@ -323,22 +428,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec Debug.LogMessage(LogEventLevel.Debug, this, "\n{0}\n", sb.ToString()); } + /// + /// Activate standby + /// public abstract void StandbyActivate(); + /// + /// Deactivate standby + /// public abstract void StandbyDeactivate(); #region Implementation of IBridgeAdvanced + /// public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); /// /// Use this method when using a plain VideoCodecControllerJoinMap /// - /// - /// - /// - /// - /// + /// codec to link + /// trilist to link + /// join to start with + /// key for custom join maps + /// bridge controller protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { @@ -355,18 +467,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecToApi(codec, trilist, joinMap); - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; - }; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; + }; } /// /// Use this method when you need to pass in a join map that extends VideoCodecControllerJoinMap /// - /// - /// - /// + /// codec to link + /// trilist to link + /// join map to use protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist {0}", trilist.ID.ToString("X")); @@ -381,16 +493,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecVolumeToApi(trilist, joinMap); - LinkVideoCodecInfoToApi(trilist, joinMap); + LinkVideoCodecInfoToApi(trilist, joinMap); - // Register for this event to link any functions that require the codec to be ready first - codec.IsReadyChange += (o, a) => - { - if (codec is IHasCodecCameras) - { - LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); - } - }; + // Register for this event to link any functions that require the codec to be ready first + codec.IsReadyChange += (o, a) => + { + if (codec is IHasCodecCameras) + { + LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); + } + }; if (codec is ICommunicationMonitor) { @@ -451,10 +563,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); } - if (codec is IHasCallHistory) - { - LinkVideoCodecCallHistoryToApi(codec as IHasCallHistory, trilist, joinMap); - } + if (codec is IHasCallHistory) + { + LinkVideoCodecCallHistoryToApi(codec as IHasCallHistory, trilist, joinMap); + } trilist.OnlineStatusChange += (device, args) => { @@ -502,39 +614,39 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); } - if (codec is IHasCallHistory) - { - UpdateCallHistory((codec as IHasCallHistory), trilist, joinMap); - } + if (codec is IHasCallHistory) + { + UpdateCallHistory((codec as IHasCallHistory), trilist, joinMap); + } SharingContentIsOnFeedback.FireUpdate(); }; } - private void LinkVideoCodecInfoToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { - trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); - trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); - trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); - trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); - trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); - trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); - trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); + private void LinkVideoCodecInfoToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); + trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); + trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); + trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); + trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); + trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); + trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); - trilist.OnlineStatusChange += (o, a) => - { - if (a.DeviceOnLine) - { - trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); - trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); - trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); - trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); - trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); - trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); - trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); - } - }; - } + trilist.OnlineStatusChange += (o, a) => + { + if (a.DeviceOnLine) + { + trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); + trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); + trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); + trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); + trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); + trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); + trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); + } + }; + } private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -570,9 +682,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - if (!(codec is IHasCameraAutoMode autoCodec)) return; + if (!(codec is IHasCameraAutoMode autoCodec)) return; - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue); trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoCodec.CameraAutoModeIsOnFeedback.BoolValue); }; @@ -587,9 +699,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - if (!(codec is IHasCameraAutoMode autoModeCodec)) return; + if (!(codec is IHasCameraAutoMode autoModeCodec)) return; - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); } @@ -628,35 +740,35 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private void LinkVideoCodecParticipantsToApi(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - // make sure to update the values when the EISC comes online - trilist.OnlineStatusChange += (sender, args) => - { - if (sender.IsOnline) - { - UpdateParticipantsXSig(codec, trilist, joinMap); - } - }; + // make sure to update the values when the EISC comes online + trilist.OnlineStatusChange += (sender, args) => + { + if (sender.IsOnline) + { + UpdateParticipantsXSig(codec, trilist, joinMap); + } + }; - // set actions and update the values when the list changes + // set actions and update the values when the list changes codec.Participants.ParticipantsListHasChanged += (sender, args) => { - SetParticipantActions(trilist, joinMap, codec.Participants.CurrentParticipants); + SetParticipantActions(trilist, joinMap, codec.Participants.CurrentParticipants); - UpdateParticipantsXSig(codec, trilist, joinMap); + UpdateParticipantsXSig(codec, trilist, joinMap); }; - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 - trilist.SetString(joinMap.CurrentParticipants.JoinNumber, "\xFC"); - UpdateParticipantsXSig(codec, trilist, joinMap); - }; + // TODO [ ] Issue #868 + trilist.SetString(joinMap.CurrentParticipants.JoinNumber, "\xFC"); + UpdateParticipantsXSig(codec, trilist, joinMap); + }; } - private void UpdateParticipantsXSig(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { + private void UpdateParticipantsXSig(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { string participantsXSig; if (codec.Participants.CurrentParticipants.Count == 0) @@ -672,48 +784,48 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig); trilist.SetUshort(joinMap.ParticipantCount.JoinNumber, (ushort)codec.Participants.CurrentParticipants.Count); - } + } - /// - /// Sets the actions for each participant in the list - /// - private void SetParticipantActions(BasicTriList trilist, VideoCodecControllerJoinMap joinMap, List currentParticipants) - { - uint index = 0; // track the index of the participant in the + /// + /// Sets the actions for each participant in the list + /// + private void SetParticipantActions(BasicTriList trilist, VideoCodecControllerJoinMap joinMap, List currentParticipants) + { + uint index = 0; // track the index of the participant in the - foreach (var participant in currentParticipants) - { - var p = participant; - if (index > MaxParticipants) break; + foreach (var participant in currentParticipants) + { + var p = participant; + if (index > MaxParticipants) break; - if (this is IHasParticipantAudioMute audioMuteCodec) - { - trilist.SetSigFalseAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index, - () => audioMuteCodec.ToggleAudioForParticipant(p.UserId)); + if (this is IHasParticipantAudioMute audioMuteCodec) + { + trilist.SetSigFalseAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index, + () => audioMuteCodec.ToggleAudioForParticipant(p.UserId)); - trilist.SetSigFalseAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index, - () => audioMuteCodec.ToggleVideoForParticipant(p.UserId)); - } + trilist.SetSigFalseAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index, + () => audioMuteCodec.ToggleVideoForParticipant(p.UserId)); + } - if (this is IHasParticipantPinUnpin pinCodec) - { - trilist.SetSigFalseAction(joinMap.ParticipantPinToggleStart.JoinNumber + index, - () => pinCodec.ToggleParticipantPinState(p.UserId, pinCodec.ScreenIndexToPinUserTo)); - } + if (this is IHasParticipantPinUnpin pinCodec) + { + trilist.SetSigFalseAction(joinMap.ParticipantPinToggleStart.JoinNumber + index, + () => pinCodec.ToggleParticipantPinState(p.UserId, pinCodec.ScreenIndexToPinUserTo)); + } - index++; - } + index++; + } - // Clear out any previously set actions - while (index < MaxParticipants) - { - trilist.ClearBoolSigAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index); - trilist.ClearBoolSigAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index); - trilist.ClearBoolSigAction(joinMap.ParticipantPinToggleStart.JoinNumber + index); + // Clear out any previously set actions + while (index < MaxParticipants) + { + trilist.ClearBoolSigAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index); + trilist.ClearBoolSigAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index); + trilist.ClearBoolSigAction(joinMap.ParticipantPinToggleStart.JoinNumber + index); - index++; - } - } + index++; + } + } private string UpdateParticipantsXSig(List currentParticipants) { @@ -733,37 +845,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (meetingIndex >= maxParticipants * offset) break; - // Debug.LogMessage(LogEventLevel.Verbose, this, - //@"Updating Participant on xsig: - //Name: {0} (s{9}) - //AudioMute: {1} (d{10}) - //VideoMute: {2} (d{11}) - //CanMuteVideo: {3} (d{12}) - //CanUMuteVideo: {4} (d{13}) - //IsHost: {5} (d{14}) - //HandIsRaised: {6} (d{15}) - //IsPinned: {7} (d{16}) - //ScreenIndexIsPinnedTo: {8} (a{17}) - //", - // participant.Name, - // participant.AudioMuteFb, - // participant.VideoMuteFb, - // participant.CanMuteVideo, - // participant.CanUnmuteVideo, - // participant.IsHost, - // participant.HandIsRaisedFb, - // participant.IsPinnedFb, - // participant.ScreenIndexIsPinnedToFb, - // stringIndex + 1, - // digitalIndex + 1, - // digitalIndex + 2, - // digitalIndex + 3, - // digitalIndex + 4, - // digitalIndex + 5, - // digitalIndex + 6, - // digitalIndex + 7, - // analogIndex + 1 - // ); + // Debug.LogMessage(LogEventLevel.Verbose, this, + //@"Updating Participant on xsig: + //Name: {0} (s{9}) + //AudioMute: {1} (d{10}) + //VideoMute: {2} (d{11}) + //CanMuteVideo: {3} (d{12}) + //CanUMuteVideo: {4} (d{13}) + //IsHost: {5} (d{14}) + //HandIsRaised: {6} (d{15}) + //IsPinned: {7} (d{16}) + //ScreenIndexIsPinnedTo: {8} (a{17}) + //", + // participant.Name, + // participant.AudioMuteFb, + // participant.VideoMuteFb, + // participant.CanMuteVideo, + // participant.CanUnmuteVideo, + // participant.IsHost, + // participant.HandIsRaisedFb, + // participant.IsPinnedFb, + // participant.ScreenIndexIsPinnedToFb, + // stringIndex + 1, + // digitalIndex + 1, + // digitalIndex + 2, + // digitalIndex + 3, + // digitalIndex + 4, + // digitalIndex + 5, + // digitalIndex + 6, + // digitalIndex + 7, + // analogIndex + 1 + // ); //digitals @@ -772,10 +884,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, participant.CanMuteVideo); tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, participant.CanUnmuteVideo); tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, participant.IsHost); - tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, participant.HandIsRaisedFb); - tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, participant.IsPinnedFb); + tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, participant.HandIsRaisedFb); + tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, participant.IsPinnedFb); - Debug.LogMessage(LogEventLevel.Verbose, this, "Index: {0} byte value: {1}", digitalIndex + 7, ComTextHelper.GetEscapedText(tokenArray[digitalIndex + 6].GetBytes())); + Debug.LogMessage(LogEventLevel.Verbose, this, "Index: {0} byte value: {1}", digitalIndex + 7, ComTextHelper.GetEscapedText(tokenArray[digitalIndex + 6].GetBytes())); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, participant.Name); @@ -812,12 +924,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec analogIndex += maxAnalogs; } - var returnString = GetXSigString(tokenArray); + var returnString = GetXSigString(tokenArray); - //Debug.LogMessage(LogEventLevel.Verbose, this, "{0}", ComTextHelper.GetEscapedText(Encoding.GetEncoding(28591).GetBytes(returnString))); + //Debug.LogMessage(LogEventLevel.Verbose, this, "{0}", ComTextHelper.GetEscapedText(Encoding.GetEncoding(28591).GetBytes(returnString))); - return returnString; + return returnString; } private void LinkVideoCodecContentSharingToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) @@ -833,7 +945,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, b => AutoShareContentWhileInCall = b); } - private List _currentMeetings = new List(); + private List _currentMeetings = new List(); private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -841,25 +953,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetUShortSigAction(joinMap.MinutesBeforeMeetingStart.JoinNumber, (i) => { - codec.CodecSchedule.MeetingWarningMinutes = i; + codec.CodecSchedule.MeetingWarningMinutes = i; }); - for (uint i = 0; i < joinMap.DialMeetingStart.JoinSpan; i++) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Setting action to Dial Meeting {0} to digital join {1}", i + 1, joinMap.DialMeetingStart.JoinNumber + i); - var joinNumber = joinMap.DialMeetingStart.JoinNumber + i; - var mtg = i + 1; - var index = (int)i; + for (uint i = 0; i < joinMap.DialMeetingStart.JoinSpan; i++) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Setting action to Dial Meeting {0} to digital join {1}", i + 1, joinMap.DialMeetingStart.JoinNumber + i); + var joinNumber = joinMap.DialMeetingStart.JoinNumber + i; + var mtg = i + 1; + var index = (int)i; - trilist.SetSigFalseAction(joinNumber, () => - { - Debug.LogMessage(LogEventLevel.Debug, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}", - mtg, joinMap.DialMeetingStart.JoinNumber + i, index, _currentMeetings[index].Id, _currentMeetings[index].Title); - if (_currentMeetings[index] != null) - Dial(_currentMeetings[index]); - }); - } + trilist.SetSigFalseAction(joinNumber, () => + { + Debug.LogMessage(LogEventLevel.Debug, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}", + mtg, joinMap.DialMeetingStart.JoinNumber + i, index, _currentMeetings[index].Id, _currentMeetings[index].Title); + if (_currentMeetings[index] != null) + Dial(_currentMeetings[index]); + }); + } codec.CodecSchedule.MeetingsListHasChanged += (sender, args) => UpdateMeetingsList(codec, trilist, joinMap); codec.CodecSchedule.MeetingEventChange += (sender, args) => @@ -870,20 +982,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec } }; - trilist.SetUShortSigAction(joinMap.MeetingsToDisplay.JoinNumber, m => MeetingsToDisplay = m); - MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]); + trilist.SetUShortSigAction(joinMap.MeetingsToDisplay.JoinNumber, m => MeetingsToDisplay = m); + MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]); - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 - trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC"); - UpdateMeetingsList(codec, trilist, joinMap); - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]); - }; - } + // TODO [ ] Issue #868 + trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC"); + UpdateMeetingsList(codec, trilist, joinMap); + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]); + }; + } private void UpdateMeetingsList(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -891,175 +1003,178 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec _currentMeetings = codec.CodecSchedule.Meetings.Where(m => m.StartTime >= currentTime || m.EndTime >= currentTime).ToList(); - if (_currentMeetings.Count == 0) - { - var emptyXSigByteArray = XSigHelpers.ClearOutputs(); - var emptyXSigString = Encoding.GetEncoding(XSigEncoding) - .GetString(emptyXSigByteArray, 0, emptyXSigByteArray.Length); + if (_currentMeetings.Count == 0) + { + var emptyXSigByteArray = XSigHelpers.ClearOutputs(); + var emptyXSigString = Encoding.GetEncoding(XSigEncoding) + .GetString(emptyXSigByteArray, 0, emptyXSigByteArray.Length); - trilist.SetString(joinMap.Schedule.JoinNumber, emptyXSigString); - return; - } + trilist.SetString(joinMap.Schedule.JoinNumber, emptyXSigString); + return; + } var meetingsData = UpdateMeetingsListXSig(_currentMeetings); trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count); - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 - trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC"); - UpdateMeetingsListXSig(_currentMeetings); - }; + // TODO [ ] Issue #868 + trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC"); + UpdateMeetingsListXSig(_currentMeetings); + }; } - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - private int _meetingsToDisplay = 3; - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - protected int MeetingsToDisplay - { - get { return _meetingsToDisplay; } - set { - _meetingsToDisplay = (ushort) (value == 0 ? 3 : value); - MeetingsToDisplayFeedback.FireUpdate(); - } - } - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - /// - /// Gets or sets the MeetingsToDisplayFeedback - /// - public IntFeedback MeetingsToDisplayFeedback { get; set; } + private int _meetingsToDisplay = 3; - private string UpdateMeetingsListXSig(List meetings) - { - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - //const int _meetingsToDisplay = 3; - const int maxDigitals = 2; - const int maxStrings = 7; - const int offset = maxDigitals + maxStrings; - var digitalIndex = maxStrings * _meetingsToDisplay; //15 - var stringIndex = 0; - var meetingIndex = 0; + /// + /// Gets or sets the number of meetings to display on the XSIG + /// + protected int MeetingsToDisplay + { + get { return _meetingsToDisplay; } + set + { + _meetingsToDisplay = (ushort)(value == 0 ? 3 : value); + MeetingsToDisplayFeedback.FireUpdate(); + } + } - var tokenArray = new XSigToken[_meetingsToDisplay * offset]; - /* - * Digitals - * IsJoinable - 1 - * IsDialable - 2 - * - * Serials - * Organizer - 1 - * Title - 2 - * Start Date - 3 - * Start Time - 4 - * End Date - 5 - * End Time - 6 - * Id - 7 - */ - + /// + /// Gets or sets the MeetingsToDisplayFeedback + /// + public IntFeedback MeetingsToDisplayFeedback { get; set; } - foreach (var meeting in meetings) - { - var currentTime = DateTime.Now; + private string UpdateMeetingsListXSig(List meetings) + { + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + //const int _meetingsToDisplay = 3; + const int maxDigitals = 2; + const int maxStrings = 7; + const int offset = maxDigitals + maxStrings; + var digitalIndex = maxStrings * _meetingsToDisplay; //15 + var stringIndex = 0; + var meetingIndex = 0; - if (meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue; + var tokenArray = new XSigToken[_meetingsToDisplay * offset]; + /* + * Digitals + * IsJoinable - 1 + * IsDialable - 2 + * + * Serials + * Organizer - 1 + * Title - 2 + * Start Date - 3 + * Start Time - 4 + * End Date - 5 + * End Time - 6 + * Id - 7 + */ - if (meetingIndex >= _meetingsToDisplay * offset) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Max Meetings reached"); - break; - } - //digitals - tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Dialable); + foreach (var meeting in meetings) + { + var currentTime = DateTime.Now; - //serials - tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); - tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture)); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); - tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture)); - tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id); + if (meeting.StartTime < currentTime && meeting.EndTime < currentTime) continue; - digitalIndex += maxDigitals; - meetingIndex += offset; - stringIndex += maxStrings; - } + if (meetingIndex >= _meetingsToDisplay * offset) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Max Meetings reached"); + break; + } - while (meetingIndex < _meetingsToDisplay * offset) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}", - meetingIndex, _meetingsToDisplay * offset); + //digitals + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Dialable); - //digitals - tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture)); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture)); + tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id); - //serials - tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); - tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); - tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); - tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty); + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; + } - digitalIndex += maxDigitals; - meetingIndex += offset; - stringIndex += maxStrings; - } + while (meetingIndex < _meetingsToDisplay * offset) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Clearing unused data. Meeting Index: {0} MaxMeetings * Offset: {1}", + meetingIndex, _meetingsToDisplay * offset); - return GetXSigString(tokenArray); - } + //digitals + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); + + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); + tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, String.Empty); + + digitalIndex += maxDigitals; + meetingIndex += offset; + stringIndex += maxStrings; + } + + return GetXSigString(tokenArray); + } private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { codec.CurrentDirectoryResultIsNotDirectoryRoot.LinkComplementInputSig( - trilist.BooleanInput[joinMap.DirectoryIsRoot.JoinNumber]); + trilist.BooleanInput[joinMap.DirectoryIsRoot.JoinNumber]); trilist.SetStringSigAction(joinMap.DirectorySearchString.JoinNumber, codec.SearchDirectory); trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i, trilist, joinMap)); - //Special Change for protected directory clear + //Special Change for protected directory clear - trilist.SetBoolSigAction(joinMap.DirectoryClearSelected.JoinNumber, (b) => SelectDirectoryEntry(_directoryCodec, 0, _directoryTrilist, _directoryJoinmap)); + trilist.SetBoolSigAction(joinMap.DirectoryClearSelected.JoinNumber, (b) => SelectDirectoryEntry(codec, 0, trilist, joinMap)); - // Report feedback for number of contact methods for selected contact + // Report feedback for number of contact methods for selected contact trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot); trilist.SetSigFalseAction(joinMap.DirectoryFolderBack.JoinNumber, codec.GetDirectoryParentFolderContents); - if (codec.DirectoryRoot != null) - { - var contactsCount = codec.DirectoryRoot.CurrentDirectoryResults.Where(c => c.ParentFolderId.Equals("root")).ToList().Count; - trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)contactsCount); + if (codec.DirectoryRoot != null) + { + var contactsCount = codec.DirectoryRoot.CurrentDirectoryResults.Where(c => c.ParentFolderId.Equals("root")).ToList().Count; + trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)contactsCount); Debug.LogMessage(LogEventLevel.Verbose, this, ">>> contactsCount: {0}", contactsCount); - var clearBytes = XSigHelpers.ClearOutputs(); + var clearBytes = XSigHelpers.ClearOutputs(); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, - Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, - codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, + codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); - Debug.LogMessage(LogEventLevel.Verbose, this, "Directory XSig Length: {0}", directoryXSig.Length); + Debug.LogMessage(LogEventLevel.Verbose, this, "Directory XSig Length: {0}", directoryXSig.Length); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); - } + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); + } codec.DirectoryResultReturned += (sender, args) => { var isRoot = codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false; - var argsCount = isRoot + var argsCount = isRoot ? args.Directory.CurrentDirectoryResults.Where(a => a.ParentFolderId.Equals("root")).ToList().Count : args.Directory.CurrentDirectoryResults.Count; @@ -1070,159 +1185,159 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetString(joinMap.DirectoryEntries.JoinNumber, Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(args.Directory, - codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); - Debug.LogMessage(LogEventLevel.Verbose, this, "Directory XSig Length: {0}", directoryXSig.Length); + var directoryXSig = UpdateDirectoryXSig(args.Directory, + codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + Debug.LogMessage(LogEventLevel.Verbose, this, "Directory XSig Length: {0}", directoryXSig.Length); trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); }; - - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; - var clearBytes = XSigHelpers.ClearOutputs(); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, - Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); - }; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; + + var clearBytes = XSigHelpers.ClearOutputs(); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); + }; } private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - if (i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return; - _selectedDirectoryItem = i == 0 ? null : codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; - trilist.SetUshort(joinMap.DirectorySelectRowFeedback.JoinNumber, i); + if (i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return; + _selectedDirectoryItem = i == 0 ? null : codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; + trilist.SetUshort(joinMap.DirectorySelectRowFeedback.JoinNumber, i); - if (_selectedDirectoryItem == null) trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false); + if (_selectedDirectoryItem == null) trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false); if (_selectedDirectoryItem is DirectoryFolder) { codec.GetDirectoryFolderContents(_selectedDirectoryItem.FolderId); - trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); - trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, _selectedDirectoryItem.Name); - trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); - trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); - trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false); - return; + trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); + trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, _selectedDirectoryItem.Name); + trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); + trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); + trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false); + return; } - // not a folder. Clear this value - trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty); + // not a folder. Clear this value + trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty); - var selectedContact = _selectedDirectoryItem as DirectoryContact; + var selectedContact = _selectedDirectoryItem as DirectoryContact; - if (selectedContact != null && selectedContact.ContactMethods.Count >= 1) - { - trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, true); - } + if (selectedContact != null && selectedContact.ContactMethods.Count >= 1) + { + trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, true); + } - trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, - selectedContact != null ? selectedContact.Name : string.Empty); + trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, + selectedContact != null ? selectedContact.Name : string.Empty); - // Allow auto dial of selected line. Always dials first contact method - if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber)) - { - if (_selectedDirectoryItem is IInvitableContact invitableEntry) - { - Dial(invitableEntry); - return; - } + // Allow auto dial of selected line. Always dials first contact method + if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber)) + { + if (_selectedDirectoryItem is IInvitableContact invitableEntry) + { + Dial(invitableEntry); + return; + } - trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, - selectedContact != null ? selectedContact.ContactMethods[0].Number : string.Empty); + trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, + selectedContact != null ? selectedContact.ContactMethods[0].Number : string.Empty); - if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) return; + if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) return; - Dial(entryToDial.ContactMethods[0].Number); - } - else - { - // If auto dial is disabled... + Dial(entryToDial.ContactMethods[0].Number); + } + else + { + // If auto dial is disabled... - if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) - { - // Clear out values and actions from last selected item - trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); - trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); - trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); - return; - } + if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) + { + // Clear out values and actions from last selected item + trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); + trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); + trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); + return; + } - trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, (ushort)entryToDial.ContactMethods.Count); + trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, (ushort)entryToDial.ContactMethods.Count); - // Update the action to dial the selected contact method - trilist.SetUShortSigAction(joinMap.SelectContactMethod.JoinNumber, (u) => - { - if (u < 1 || u > entryToDial.ContactMethods.Count) return; + // Update the action to dial the selected contact method + trilist.SetUShortSigAction(joinMap.SelectContactMethod.JoinNumber, (u) => + { + if (u < 1 || u > entryToDial.ContactMethods.Count) return; - trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber, () => Dial(entryToDial.ContactMethods[u - 1].Number)); - }); + trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber, () => Dial(entryToDial.ContactMethods[u - 1].Number)); + }); - // Sets DirectoryDialSelectedLine join action to dial first contact method - trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number)); + // Sets DirectoryDialSelectedLine join action to dial first contact method + trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number)); - var clearBytes = XSigHelpers.ClearOutputs(); + var clearBytes = XSigHelpers.ClearOutputs(); - trilist.SetString(joinMap.ContactMethods.JoinNumber, - Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var contactMethodsXSig = UpdateContactMethodsXSig(entryToDial); + trilist.SetString(joinMap.ContactMethods.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var contactMethodsXSig = UpdateContactMethodsXSig(entryToDial); - trilist.SetString(joinMap.ContactMethods.JoinNumber, contactMethodsXSig); - } + trilist.SetString(joinMap.ContactMethods.JoinNumber, contactMethodsXSig); + } } - /// - /// Generates the XSig data representing the available contact methods for the selected DirectoryContact - /// - /// - /// - private string UpdateContactMethodsXSig(DirectoryContact contact) - { - const int maxMethods = 10; - const int maxStrings = 3; - const int offset = maxStrings; - var stringIndex = 0; - var arrayIndex = 0; - // Create a new token array and set the size to the number of methods times the total number of signals - var tokenArray = new XSigToken[maxMethods * offset]; + /// + /// Generates the XSig data representing the available contact methods for the selected DirectoryContact + /// + /// + /// + private string UpdateContactMethodsXSig(DirectoryContact contact) + { + const int maxMethods = 10; + const int maxStrings = 3; + const int offset = maxStrings; + var stringIndex = 0; + var arrayIndex = 0; + // Create a new token array and set the size to the number of methods times the total number of signals + var tokenArray = new XSigToken[maxMethods * offset]; - Debug.LogMessage(LogEventLevel.Verbose, this, "Creating XSIG token array with size {0}", maxMethods * offset); + Debug.LogMessage(LogEventLevel.Verbose, this, "Creating XSIG token array with size {0}", maxMethods * offset); - // TODO: Add code to generate XSig data - foreach (var method in contact.ContactMethods) - { - if (arrayIndex >= maxMethods * offset) - break; + // TODO: Add code to generate XSig data + foreach (var method in contact.ContactMethods) + { + if (arrayIndex >= maxMethods * offset) + break; - //serials - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, method.Number); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, method.ContactMethodId.ToString()); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, method.Device.ToString()); + //serials + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, method.Number); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, method.ContactMethodId.ToString()); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, method.Device.ToString()); arrayIndex += offset; stringIndex += maxStrings; - } + } - while (arrayIndex < maxMethods) - { - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); + while (arrayIndex < maxMethods) + { + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); arrayIndex += offset; stringIndex += maxStrings; - } + } - return GetXSigString(tokenArray); - } + return GetXSigString(tokenArray); + } private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) { @@ -1267,7 +1382,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec return GetXSigString(tokenArray); } - private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { trilist.SetSigFalseAction(joinMap.ManualDial.JoinNumber, () => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue)); @@ -1275,31 +1390,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //End All calls trilist.SetSigFalseAction(joinMap.EndAllCalls.JoinNumber, EndAllCalls); - //End a specific call, specified by index. Maximum 8 calls supported - for (int i = 0; i < joinMap.EndCallStart.JoinSpan; i++) - { - var callIndex = i; + //End a specific call, specified by index. Maximum 8 calls supported + for (int i = 0; i < joinMap.EndCallStart.JoinSpan; i++) + { + var callIndex = i; - trilist.SetSigFalseAction((uint)(joinMap.EndCallStart.JoinNumber + i), () => - { + trilist.SetSigFalseAction((uint)(joinMap.EndCallStart.JoinNumber + i), () => + { - if (callIndex < 0 || callIndex >= ActiveCalls.Count) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Cannot end call. No call found at index: {0}", callIndex); - return; - } + if (callIndex < 0 || callIndex >= ActiveCalls.Count) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Cannot end call. No call found at index: {0}", callIndex); + return; + } - var call = ActiveCalls[callIndex]; - if (call != null) - { - EndCall(call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "[End Call] Unable to find call at index '{0}'", i); - } - }); - } + var call = ActiveCalls[callIndex]; + if (call != null) + { + EndCall(call); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "[End Call] Unable to find call at index '{0}'", i); + } + }); + } trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); @@ -1311,18 +1426,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec Debug.LogMessage(LogEventLevel.Debug, this, "Call is incoming: {0}", args.CallItem.Direction == eCodecCallDirection.Incoming); trilist.SetBool(joinMap.IncomingCall.JoinNumber, args.CallItem.Direction == eCodecCallDirection.Incoming && args.CallItem.Status == eCodecCallStatus.Ringing); - if (args.CallItem.Direction == eCodecCallDirection.Incoming) - { - trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem)); - trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem)); - trilist.SetString(joinMap.IncomingCallName.JoinNumber, args.CallItem.Name); - trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, args.CallItem.Number); - } - else - { - trilist.SetString(joinMap.IncomingCallName.JoinNumber, string.Empty); - trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, string.Empty); - } + if (args.CallItem.Direction == eCodecCallDirection.Incoming) + { + trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem)); + trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem)); + trilist.SetString(joinMap.IncomingCallName.JoinNumber, args.CallItem.Name); + trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, args.CallItem.Number); + } + else + { + trilist.SetString(joinMap.IncomingCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, string.Empty); + } trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); @@ -1330,92 +1445,92 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count); }; - if (this is IJoinCalls joinCodec) - { - trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls()); - - for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++) - { - trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () => - { - var call = ActiveCalls[i]; - if (call != null) - { - joinCodec.JoinCall(call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "[Join Call] Unable to find call at index '{0}'", i); - } - }); - } - } - - if (this is IHasCallHold holdCodec) - { - trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () => - { - foreach (var call in ActiveCalls) - { - holdCodec.HoldCall(call); - } - }); - - for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++) - { - var index = i; - - trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () => - { - if (index < 0 || index >= ActiveCalls.Count) return; - - var call = ActiveCalls[index]; - if (call != null) - { - holdCodec.HoldCall(call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "[Hold Call] Unable to find call at index '{0}'", i); - } - }); - - trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () => - { - if (index < 0 || index >= ActiveCalls.Count) return; - - var call = ActiveCalls[index]; - if (call != null) - { - holdCodec.ResumeCall(call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "[Resume Call] Unable to find call at index '{0}'", i); - } - }); - } - } - - - - trilist.OnlineStatusChange += (device, args) => + if (this is IJoinCalls joinCodec) { - if (!args.DeviceOnLine) return; + trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls()); - // TODO [ ] #983 - Debug.LogMessage(LogEventLevel.Information, this, "LinkVideoCodecCallControlsToApi: device is {0}, IsInCall {1}", args.DeviceOnLine ? "online" : "offline", IsInCall); - trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); - trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC"); - trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); - }; + for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++) + { + trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () => + { + var call = ActiveCalls[i]; + if (call != null) + { + joinCodec.JoinCall(call); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "[Join Call] Unable to find call at index '{0}'", i); + } + }); + } + } + + if (this is IHasCallHold holdCodec) + { + trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () => + { + foreach (var call in ActiveCalls) + { + holdCodec.HoldCall(call); + } + }); + + for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++) + { + var index = i; + + trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () => + { + if (index < 0 || index >= ActiveCalls.Count) return; + + var call = ActiveCalls[index]; + if (call != null) + { + holdCodec.HoldCall(call); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "[Hold Call] Unable to find call at index '{0}'", i); + } + }); + + trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () => + { + if (index < 0 || index >= ActiveCalls.Count) return; + + var call = ActiveCalls[index]; + if (call != null) + { + holdCodec.ResumeCall(call); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "[Resume Call] Unable to find call at index '{0}'", i); + } + }); + } + } + + + + trilist.OnlineStatusChange += (device, args) => +{ + if (!args.DeviceOnLine) return; + + // TODO [ ] #983 + Debug.LogMessage(LogEventLevel.Information, this, "LinkVideoCodecCallControlsToApi: device is {0}, IsInCall {1}", args.DeviceOnLine ? "online" : "offline", IsInCall); + trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); + trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC"); + trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); +}; } private string UpdateCallStatusXSig() { const int maxCalls = 8; const int maxStrings = 6; - const int maxDigitals = 2; + const int maxDigitals = 2; const int offset = maxStrings + maxDigitals; var stringIndex = 0; var digitalIndex = maxStrings * maxCalls; @@ -1428,40 +1543,40 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (arrayIndex >= maxCalls * offset) break; //digitals - tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); //serials - tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); - tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); - if(call.Duration != null) - { - // May need to verify correct string format here - var dur = string.Format("{0:c}", call.Duration); - tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, dur); - } + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); + if (call.Duration != null) + { + // May need to verify correct string format here + var dur = string.Format("{0:c}", call.Duration); + tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, dur); + } arrayIndex += offset; stringIndex += maxStrings; - digitalIndex += maxDigitals; + digitalIndex += maxDigitals; } - while (arrayIndex < maxCalls * offset) + while (arrayIndex < maxCalls * offset) { //digitals - tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); - //serials - tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); - tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); - tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); arrayIndex += offset; stringIndex += maxStrings; @@ -1473,55 +1588,55 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec private void LinkVideoCodecDtmfToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmfAction("0", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmfAction("1", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmfAction("2", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmfAction("3", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmfAction("4", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmfAction("5", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmfAction("6", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmfAction("7", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmfAction("8", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmfAction("9", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmfAction("*", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmfAction("#", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmfAction("0", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmfAction("1", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmfAction("2", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmfAction("3", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmfAction("4", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmfAction("5", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmfAction("6", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmfAction("7", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmfAction("8", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmfAction("9", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmfAction("*", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmfAction("#", trilist, joinMap)); } - /// - /// Sends the specified string as a DTMF command. - /// Reads the value of the SendDtmfToSpecificCallInstance digital join and SelectCall analog join to determine - /// Whther to send to a specific call index or to the last connected call - /// - /// - /// - /// - private void SendDtmfAction(string s, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { - if (!trilist.GetBool(joinMap.SendDtmfToSpecificCallIndex.JoinNumber)) - { - SendDtmf(s); - } - else - { - var callIndex = trilist.GetUshort(joinMap.SelectCall.JoinNumber); - if (callIndex > 0 && callIndex <= 8) - { - var call = ActiveCalls[callIndex - 1]; - if (call != null && call.IsActiveCall) - { - SendDtmf(s, call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Warning: No call found at index {0} or call is not active.", callIndex); - } - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Warning: Invalid call index specified. Please use a value of 1-8."); - } - } - } + /// + /// Sends the specified string as a DTMF command. + /// Reads the value of the SendDtmfToSpecificCallInstance digital join and SelectCall analog join to determine + /// Whther to send to a specific call index or to the last connected call + /// + /// + /// + /// + private void SendDtmfAction(string s, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + if (!trilist.GetBool(joinMap.SendDtmfToSpecificCallIndex.JoinNumber)) + { + SendDtmf(s); + } + else + { + var callIndex = trilist.GetUshort(joinMap.SelectCall.JoinNumber); + if (callIndex > 0 && callIndex <= 8) + { + var call = ActiveCalls[callIndex - 1]; + if (call != null && call.IsActiveCall) + { + SendDtmf(s, call); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Warning: No call found at index {0} or call is not active.", callIndex); + } + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Warning: Invalid call index specified. Please use a value of 1-8."); + } + } + } private void LinkVideoCodecCameraLayoutsToApi(IHasCodecLayouts codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -1537,45 +1652,45 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec codec.CameraAutoModeIsOnFeedback.OutputChange += (o, a) => { - if (codec is IHasCameraOff offCodec) - { - if (offCodec.CameraIsOffFeedback.BoolValue) - { - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); - return; - } + if (codec is IHasCameraOff offCodec) + { + if (offCodec.CameraIsOffFeedback.BoolValue) + { + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + return; + } - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - return; - } + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + return; + } - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); }; - if (codec is IHasCameraOff offModeCodec) - { - if (offModeCodec.CameraIsOffFeedback.BoolValue) - { - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); - return; - } + if (codec is IHasCameraOff offModeCodec) + { + if (offModeCodec.CameraIsOffFeedback.BoolValue) + { + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); + return; + } - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - return; - } + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + return; + } - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); } @@ -1595,9 +1710,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.TiltUp(); + if (b) camera.TiltUp(); else camera.TiltStop(); }); @@ -1605,27 +1720,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.TiltDown(); + if (b) camera.TiltDown(); else camera.TiltStop(); }); trilist.SetBoolSigAction(joinMap.CameraPanLeft.JoinNumber, (b) => { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.PanLeft(); + if (b) camera.PanLeft(); else camera.PanStop(); }); trilist.SetBoolSigAction(joinMap.CameraPanRight.JoinNumber, (b) => { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.PanRight(); + if (b) camera.PanRight(); else camera.PanStop(); }); @@ -1633,9 +1748,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.ZoomIn(); + if (b) camera.ZoomIn(); else camera.ZoomStop(); }); @@ -1643,83 +1758,83 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.ZoomOut(); + if (b) camera.ZoomOut(); else camera.ZoomStop(); }); - trilist.SetBoolSigAction(joinMap.CameraFocusNear.JoinNumber, (b) => - { - if (codec.SelectedCamera == null) return; + trilist.SetBoolSigAction(joinMap.CameraFocusNear.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; - if (b) camera.FocusNear(); - else camera.FocusStop(); - }); + if (b) camera.FocusNear(); + else camera.FocusStop(); + }); - trilist.SetBoolSigAction(joinMap.CameraFocusFar.JoinNumber, (b) => - { - if (codec.SelectedCamera == null) return; + trilist.SetBoolSigAction(joinMap.CameraFocusFar.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; - if (b) camera.FocusFar(); - else camera.FocusStop(); - }); + if (b) camera.FocusFar(); + else camera.FocusStop(); + }); - trilist.SetSigFalseAction(joinMap.CameraFocusAuto.JoinNumber, () => - { - if (codec.SelectedCamera == null) return; + trilist.SetSigFalseAction(joinMap.CameraFocusAuto.JoinNumber, () => + { + if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; - camera.TriggerAutoFocus(); - }); + camera.TriggerAutoFocus(); + }); - // Camera count - trilist.SetUshort(joinMap.CameraCount.JoinNumber, (ushort)codec.Cameras.Count); + // Camera count + trilist.SetUshort(joinMap.CameraCount.JoinNumber, (ushort)codec.Cameras.Count); - // Camera names - for (uint i = 0; i < joinMap.CameraNamesFb.JoinSpan; i++) - { - //Check the count first - if (i < codec.Cameras.Count && codec.Cameras[(int)i] != null) - { - trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, codec.Cameras[(int)i].Name); - } - else - { - trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, ""); - } - } + // Camera names + for (uint i = 0; i < joinMap.CameraNamesFb.JoinSpan; i++) + { + //Check the count first + if (i < codec.Cameras.Count && codec.Cameras[(int)i] != null) + { + trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, codec.Cameras[(int)i].Name); + } + else + { + trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, ""); + } + } //Camera Select trilist.SetUShortSigAction(joinMap.CameraNumberSelect.JoinNumber, (i) => { - if (i > 0 && i <= codec.Cameras.Count) - { - codec.SelectCamera(codec.Cameras[i - 1].Key); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Unable to select. No camera found at index {0}", i); - } + if (i > 0 && i <= codec.Cameras.Count) + { + codec.SelectCamera(codec.Cameras[i - 1].Key); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Unable to select. No camera found at index {0}", i); + } }); - // Set initial selected camera feedback - if (codec.SelectedCamera != null) - { - trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)codec.Cameras.FindIndex((c) => c.Key == codec.SelectedCamera.Key)); - } + // Set initial selected camera feedback + if (codec.SelectedCamera != null) + { + trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)codec.Cameras.FindIndex((c) => c.Key == codec.SelectedCamera.Key)); + } codec.CameraSelected += (sender, args) => { var i = (ushort)codec.Cameras.FindIndex((c) => c.Key == args.SelectedCamera.Key); - trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)(i + 1)); + trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)(i + 1)); if (codec is IHasCodecRoomPresets) { @@ -1766,11 +1881,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec }); - // Far End Presets - trilist.SetUShortSigAction(joinMap.FarEndPresetSelect.JoinNumber, (i) => - { - presetCodec.SelectFarEndPreset(i); - }); + // Far End Presets + trilist.SetUShortSigAction(joinMap.FarEndPresetSelect.JoinNumber, (i) => + { + presetCodec.SelectFarEndPreset(i); + }); trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, @@ -1781,105 +1896,105 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000); }); - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 - trilist.SetString(joinMap.CameraPresetNames.JoinNumber, "\xFC"); - SetCameraPresetNames(presetCodec.NearEndPresets); - }; + // TODO [ ] Issue #868 + trilist.SetString(joinMap.CameraPresetNames.JoinNumber, "\xFC"); + SetCameraPresetNames(presetCodec.NearEndPresets); + }; } - // Following fields only used for Bridging - private int _selectedRecentCallItemIndex; - private DirectoryItem _selectedDirectoryItem; + // Following fields only used for Bridging + private int _selectedRecentCallItemIndex; + private DirectoryItem _selectedDirectoryItem; - private void LinkVideoCodecCallHistoryToApi(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { - codec.CallHistory.RecentCallsListHasChanged += (o, a) => - { - UpdateCallHistory(codec, trilist, joinMap); - }; + private void LinkVideoCodecCallHistoryToApi(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + codec.CallHistory.RecentCallsListHasChanged += (o, a) => + { + UpdateCallHistory(codec, trilist, joinMap); + }; - // Selected item action and feedback - trilist.SetUShortSigAction(joinMap.SelectRecentCallItem.JoinNumber, (u) => - { - if (u == 0 || u > codec.CallHistory.RecentCalls.Count) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Recent Call History index out of range"); - return; - } + // Selected item action and feedback + trilist.SetUShortSigAction(joinMap.SelectRecentCallItem.JoinNumber, (u) => + { + if (u == 0 || u > codec.CallHistory.RecentCalls.Count) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Recent Call History index out of range"); + return; + } - _selectedRecentCallItemIndex = (int)(u - 1); - trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u); + _selectedRecentCallItemIndex = (int)(u - 1); + trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u); - var _selectedRecentCallItem = codec.CallHistory.RecentCalls[_selectedRecentCallItemIndex]; - - if (_selectedRecentCallItem != null) - { - trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name); - trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, _selectedRecentCallItem.Number); - trilist.SetSigFalseAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber, () => codec.RemoveCallHistoryEntry(_selectedRecentCallItem)); - trilist.SetSigFalseAction(joinMap.DialSelectedRecentCallItem.JoinNumber, () => this.Dial(_selectedRecentCallItem.Number)); - } - else - { - trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); - trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); - trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DialSelectedRecentCallItem.JoinNumber); - } - }); - } + var _selectedRecentCallItem = codec.CallHistory.RecentCalls[_selectedRecentCallItemIndex]; + + if (_selectedRecentCallItem != null) + { + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, _selectedRecentCallItem.Number); + trilist.SetSigFalseAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber, () => codec.RemoveCallHistoryEntry(_selectedRecentCallItem)); + trilist.SetSigFalseAction(joinMap.DialSelectedRecentCallItem.JoinNumber, () => this.Dial(_selectedRecentCallItem.Number)); + } + else + { + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); + trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DialSelectedRecentCallItem.JoinNumber); + } + }); + } - private void UpdateCallHistory(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { - // Clear out selected item - _selectedRecentCallItemIndex = 0; + private void UpdateCallHistory(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + // Clear out selected item + _selectedRecentCallItemIndex = 0; - trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, 0); - trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); - trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); - trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); - // + trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, 0); + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); + trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); + // - trilist.SetUshort(joinMap.RecentCallCount.JoinNumber, (ushort)codec.CallHistory.RecentCalls.Count); + trilist.SetUshort(joinMap.RecentCallCount.JoinNumber, (ushort)codec.CallHistory.RecentCalls.Count); - // Update the call history joins - var maxItems = joinMap.RecentCallNamesStart.JoinSpan; + // Update the call history joins + var maxItems = joinMap.RecentCallNamesStart.JoinSpan; - // Create history - uint index = 0; - for (uint i = 0; i < maxItems && i < codec.CallHistory.RecentCalls.Count; i++) - { - trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].Name); - trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].StartTime.ToShortTimeString()); - trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)codec.CallHistory.RecentCalls[(int)i].OccurrenceType); - //i++; - index = i; - } - - //foreach(var item in codec.CallHistory.RecentCalls) - //{ - // trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name); - // trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString()); - // trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType); - // i++; - //} + // Create history + uint index = 0; + for (uint i = 0; i < maxItems && i < codec.CallHistory.RecentCalls.Count; i++) + { + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].Name); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].StartTime.ToShortTimeString()); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)codec.CallHistory.RecentCalls[(int)i].OccurrenceType); + //i++; + index = i; + } - // Clears existing items - for (uint j = index; j < maxItems; j++) - { - trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + j, string.Empty); - trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + j, string.Empty); - trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + j, 0); - } - } + //foreach(var item in codec.CallHistory.RecentCalls) + //{ + // trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name); + // trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString()); + // trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType); + // i++; + //} - private string SetCameraPresetNames(IEnumerable presets) + // Clears existing items + for (uint j = index; j < maxItems; j++) + { + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + j, string.Empty); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + j, string.Empty); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + j, 0); + } + } + + private string SetCameraPresetNames(IEnumerable presets) { return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); } @@ -1925,159 +2040,4 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec #endregion } - - - /// - /// Represents a CodecPhonebookSyncState - /// - public class CodecPhonebookSyncState : IKeyed - { - private bool _InitialSyncComplete; - - public CodecPhonebookSyncState(string key) - { - Key = key; - - CodecDisconnected(); - } - - public bool InitialSyncComplete - { - get { return _InitialSyncComplete; } - private set - { - if (value == true) - { - InitialSyncCompleted?.Invoke(this, new EventArgs()); - } - _InitialSyncComplete = value; - } - } - - /// - /// Gets or sets the InitialPhonebookFoldersWasReceived - /// - public bool InitialPhonebookFoldersWasReceived { get; private set; } - - /// - /// Gets or sets the NumberOfContactsWasReceived - /// - public bool NumberOfContactsWasReceived { get; private set; } - - /// - /// Gets or sets the PhonebookRootEntriesWasRecieved - /// - public bool PhonebookRootEntriesWasRecieved { get; private set; } - - /// - /// Gets or sets the PhonebookHasFolders - /// - public bool PhonebookHasFolders { get; private set; } - - /// - /// Gets or sets the NumberOfContacts - /// - public int NumberOfContacts { get; private set; } - - #region IKeyed Members - - /// - /// Gets or sets the Key - /// - public string Key { get; private set; } - - #endregion - - public event EventHandler InitialSyncCompleted; - - /// - /// InitialPhonebookFoldersReceived method - /// - public void InitialPhonebookFoldersReceived() - { - InitialPhonebookFoldersWasReceived = true; - - CheckSyncStatus(); - } - - /// - /// PhonebookRootEntriesReceived method - /// - public void PhonebookRootEntriesReceived() - { - PhonebookRootEntriesWasRecieved = true; - - CheckSyncStatus(); - } - - /// - /// SetPhonebookHasFolders method - /// - public void SetPhonebookHasFolders(bool value) - { - PhonebookHasFolders = value; - - Debug.LogMessage(LogEventLevel.Debug, this, "Phonebook has folders: {0}", PhonebookHasFolders); - } - - /// - /// SetNumberOfContacts method - /// - public void SetNumberOfContacts(int contacts) - { - NumberOfContacts = contacts; - NumberOfContactsWasReceived = true; - - Debug.LogMessage(LogEventLevel.Debug, this, "Phonebook contains {0} contacts.", NumberOfContacts); - - CheckSyncStatus(); - } - - /// - /// CodecDisconnected method - /// - public void CodecDisconnected() - { - InitialPhonebookFoldersWasReceived = false; - PhonebookHasFolders = false; - NumberOfContacts = 0; - NumberOfContactsWasReceived = false; - } - - private void CheckSyncStatus() - { - if (InitialPhonebookFoldersWasReceived && NumberOfContactsWasReceived && PhonebookRootEntriesWasRecieved) - { - InitialSyncComplete = true; - Debug.LogMessage(LogEventLevel.Debug, this, "Initial Phonebook Sync Complete!"); - } - else - { - InitialSyncComplete = false; - } - } - } - /// - /// Represents a CodecCommandWithLabel - /// - public class CodecCommandWithLabel - { - /// - /// Gets or sets the Command - /// - public string Command { get; private set; } - /// - /// Gets or sets the Label - /// - public string Label { get; private set; } - - public CodecCommandWithLabel(string command, string label) - { - Command = command; - Label = label; - } - } - - - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs index 7650b430..8c9f0451 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.Cameras; @@ -9,12 +11,12 @@ namespace PepperDash.Essentials.AppServer.Messengers /// /// Messenger for a CameraBase device /// - public class CameraBaseMessenger : MessengerBase + public class CameraBaseMessenger : MessengerBase where T : IKeyed { /// /// Gets or sets the Camera /// - public CameraBase Camera { get; set; } + public T Camera { get; set; } /// /// Constructor @@ -22,10 +24,13 @@ namespace PepperDash.Essentials.AppServer.Messengers /// /// /// - public CameraBaseMessenger(string key, CameraBase camera, string messagePath) - : base(key, messagePath, camera) + public CameraBaseMessenger(string key, T camera, string messagePath) + : base(key, messagePath, camera as IKeyName) { - Camera = camera ?? throw new ArgumentNullException("camera"); + if (camera == null) + throw new ArgumentNullException(nameof(camera)); + + Camera = camera; if (Camera is IHasCameraPresets presetsCamera) @@ -178,19 +183,44 @@ namespace PepperDash.Essentials.AppServer.Messengers private void SendCameraFullMessageObject(string id = null) { var presetList = new List(); + CameraCapabilities capabilities = null; if (Camera is IHasCameraPresets presetsCamera) presetList = presetsCamera.Presets; - PostStatusMessage(JToken.FromObject(new + if (Camera is ICameraCapabilities cameraCapabilities) + capabilities = new CameraCapabilities + { + CanPan = cameraCapabilities.CanPan, + CanTilt = cameraCapabilities.CanTilt, + CanZoom = cameraCapabilities.CanZoom, + CanFocus = cameraCapabilities.CanFocus + + }; + + if (Camera is CameraBase cameraBase) + capabilities = new CameraCapabilities + { + CanPan = cameraBase.CanPan, + CanTilt = cameraBase.CanTilt, + CanZoom = cameraBase.CanZoom, + CanFocus = cameraBase.CanFocus + + }; + + var message = new CameraStateMessage { - cameraManualSupported = Camera is IHasCameraControls, - cameraAutoSupported = Camera is IHasCameraAutoMode, - cameraOffSupported = Camera is IHasCameraOff, - cameraMode = GetCameraMode(), - hasPresets = Camera is IHasCameraPresets, - presets = presetList - }), id + CameraManualSupported = Camera is IHasCameraControls, + CameraAutoSupported = Camera is IHasCameraAutoMode, + CameraOffSupported = Camera is IHasCameraOff, + CameraMode = (eCameraControlMode)Enum.Parse(typeof(eCameraControlMode), GetCameraMode(), true), + HasPresets = Camera is IHasCameraPresets, + Presets = presetList, + Capabilities = capabilities, + IsFarEnd = Camera is IAmFarEndCamera + }; + + PostStatusMessage(message, id ); } @@ -210,4 +240,59 @@ namespace PepperDash.Essentials.AppServer.Messengers return m; } } + + /// + /// State message for a camera device + /// + public class CameraStateMessage : DeviceStateMessageBase + { + /// + /// Indicates whether the camera supports manual control + /// + [JsonProperty("cameraManualSupported", NullValueHandling = NullValueHandling.Ignore)] + public bool CameraManualSupported { get; set; } + + /// + /// Indicates whether the camera supports auto control + /// + [JsonProperty("cameraAutoSupported", NullValueHandling = NullValueHandling.Ignore)] + public bool CameraAutoSupported { get; set; } + + /// + /// Indicates whether the camera supports off control + /// + [JsonProperty("cameraOffSupported", NullValueHandling = NullValueHandling.Ignore)] + public bool CameraOffSupported { get; set; } + + /// + /// Indicates the current camera control mode + /// + [JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public eCameraControlMode CameraMode { get; set; } + + /// + /// Indicates whether the camera has presets + /// + [JsonProperty("hasPresets", NullValueHandling = NullValueHandling.Ignore)] + public bool HasPresets { get; set; } + + /// + /// List of presets if the camera supports them + /// + [JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)] + public List Presets { get; set; } + + /// + /// Indicates the capabilities of the camera + /// + [JsonProperty("capabilities", NullValueHandling = NullValueHandling.Ignore)] + public CameraCapabilities Capabilities { get; set; } + + /// + /// Indicates whether the camera is a far end camera + /// + [JsonProperty("isFarEnd", NullValueHandling = NullValueHandling.Ignore)] + public bool IsFarEnd { get; set; } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs index 7099e52c..00c2c2fe 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs @@ -1,17 +1,14 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using Newtonsoft.Json; using PepperDash.Essentials.Devices.Common.Cameras; +using System; +using System.Collections.Generic; namespace PepperDash.Essentials.AppServer.Messengers { /// /// Messenger for devices that implement the IHasCameras interface. /// + [Obsolete("Use IHasCamerasWithControlsMessenger instead. This class will be removed in a future version")] public class IHasCamerasMessenger : MessengerBase { /// diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasWithControlMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasWithControlMessenger.cs new file mode 100644 index 00000000..cce07dcd --- /dev/null +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasWithControlMessenger.cs @@ -0,0 +1,137 @@ +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Core.Logging; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Devices.Common.Cameras; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace PepperDash.Essentials.AppServer.Messengers +{ + /// + /// Messenger for devices that implement the IHasCameras interface. + /// + public class IHasCamerasWithControlMessenger : MessengerBase + { + /// + /// Device being bridged that implements IHasCameras interface. + /// + public IHasCamerasWithControls CameraController { get; private set; } + + /// + /// Messenger for devices that implement IHasCameras interface. + /// + /// + /// + /// + /// + public IHasCamerasWithControlMessenger(string key, string messagePath, IHasCamerasWithControls cameraController) + : base(key, messagePath, cameraController) + { + CameraController = cameraController ?? throw new ArgumentNullException("cameraController"); + CameraController.CameraSelected += CameraController_CameraSelected; + } + + private void CameraController_CameraSelected(object sender, CameraSelectedEventArgs e) + { + var selectedCamera = new KeyName + { + Key = e.SelectedCamera.Key, + Name = e.SelectedCamera.Name + }; + + PostStatusMessage(new IHasCamerasWithControlsStateMessage + { + SelectedCamera = selectedCamera + }); + } + + /// + /// Registers the actions for this messenger. + /// + /// + protected override void RegisterActions() + { + base.RegisterActions(); + + AddAction("/fullStatus", (id, context) => SendFullStatus(id)); + + AddAction("/cameraListStatus", (id, content) => SendFullStatus(id)); + + AddAction("/selectCamera", (id, content) => + { + var cameraKey = content?.ToObject(); + + if (!string.IsNullOrEmpty(cameraKey)) + { + CameraController.SelectCamera(cameraKey); + } + else + { + throw new ArgumentException("Content must be a string representing the camera key"); + } + }); + } + + private void SendFullStatus(string clientId) + { + var cameraList = new List(); + KeyName selectedCamera = null; + + foreach (var cam in CameraController.Cameras) + { + cameraList.Add(new KeyName{ + Key = cam.Key, + Name = cam.Name + }); + } + + if (CameraController.SelectedCamera != null) + { + selectedCamera = new KeyName + { + Key = CameraController.SelectedCamera.Key, + Name = CameraController.SelectedCamera.Name + }; + } + + var state = new IHasCamerasWithControlsStateMessage + { + CameraList = cameraList, + SelectedCamera = selectedCamera + }; + + PostStatusMessage(state, clientId); + } + } + + /// + /// State message for devices that implement the IHasCameras interface. + /// + public class IHasCamerasWithControlsStateMessage : DeviceStateMessageBase + { + /// + /// List of cameras available in the device. + /// + [JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)] + public List CameraList { get; set; } + + /// + /// The currently selected camera on the device. + /// + [JsonProperty("selectedCamera", NullValueHandling = NullValueHandling.Ignore)] + public IKeyName SelectedCamera { get; set; } + } + + class KeyName : IKeyName + { + public string Key { get; set; } + public string Name { get; set; } + public KeyName() + { + Key = ""; + Name = ""; + } + } +} diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs index 36d73a3e..8e2f8f3e 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs @@ -16,6 +16,8 @@ namespace PepperDash.Essentials.AppServer.Messengers private readonly string _propName; + private List _itemKeys = new List(); + /// /// Constructs a messenger for a device that implements ISelectableItems /// @@ -39,9 +41,35 @@ namespace PepperDash.Essentials.AppServer.Messengers AddAction("/itemsStatus", (id, content) => SendFullStatus(id)); + AddAction("/selectItem", (id, content) => + { + try + { + var key = content.ToObject(); + + if (key == null) + { + this.LogError("No key specified to select"); + return; + } + if (itemDevice.Items.ContainsKey((TKey)Convert.ChangeType(key, typeof(TKey)))) + { + itemDevice.Items[(TKey)Convert.ChangeType(key, typeof(TKey))].Select(); + } + else + { + this.LogError("Key {0} not found in items", key); + } + } + catch (Exception e) + { + this.LogError("Error selecting item: {0}", e.Message); + } + }); + itemDevice.ItemsUpdated += (sender, args) => { - SendFullStatus(); + SetItems(); }; itemDevice.CurrentItemChanged += (sender, args) => @@ -49,23 +77,47 @@ namespace PepperDash.Essentials.AppServer.Messengers SendFullStatus(); }; - foreach (var input in itemDevice.Items) + SetItems(); + } + + /// + /// Sets the items and registers their update events + /// + private void SetItems() + { + if (_itemKeys != null && _itemKeys.Count > 0) { - var key = input.Key; - var localItem = input.Value; + /// Clear out any existing item actions + foreach (var item in _itemKeys) + { + RemoveAction($"/{item}"); + } + + _itemKeys.Clear(); + } + + foreach (var item in itemDevice.Items) + { + var key = item.Key; + var localItem = item.Value; AddAction($"/{key}", (id, content) => { localItem.Select(); }); - localItem.ItemUpdated += (sender, args) => - { - SendFullStatus(); - }; + _itemKeys.Add(key.ToString()); + + localItem.ItemUpdated -= LocalItem_ItemUpdated; + localItem.ItemUpdated += LocalItem_ItemUpdated; } } + private void LocalItem_ItemUpdated(object sender, EventArgs e) + { + SendFullStatus(); + } + private void SendFullStatus(string id = null) { try diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs index 0579c1f6..d6a40ede 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs @@ -405,14 +405,15 @@ namespace PepperDash.Essentials messengerAdded = true; } - if (device is CameraBase cameraDevice) + // Default to IHasCameraControls if CameraBase and IHasCameraControls + if (device is CameraBase cameraDevice && !(device is IHasCameraControls)) { this.LogVerbose( "Adding CameraBaseMessenger for {deviceKey}", device.Key ); - var cameraMessenger = new CameraBaseMessenger( + var cameraMessenger = new CameraBaseMessenger( $"{device.Key}-cameraBase-{Key}", cameraDevice, $"/device/{device.Key}" @@ -423,6 +424,21 @@ namespace PepperDash.Essentials messengerAdded = true; } + if (device is IHasCameraControls cameraControlDev) + { + this.LogVerbose( + "Adding IHasCamerasWithControlMessenger for {deviceKey}", + device.Key + ); + var cameraControlMessenger = new CameraBaseMessenger( + $"{device.Key}-hasCamerasWithControls-{Key}", + cameraControlDev, + $"/device/{device.Key}" + ); + AddDefaultDeviceMessenger(cameraControlMessenger); + messengerAdded = true; + } + if (device is BlueJeansPc) { this.LogVerbose( @@ -975,6 +991,19 @@ namespace PepperDash.Essentials messengerAdded = true; } + if (device is IHasCamerasWithControls cameras2) + { + this.LogVerbose("Adding IHasCamerasWithControlsMessenger for {deviceKey}", device.Key + ); + var messenger = new IHasCamerasWithControlMessenger( + $"{device.Key}-cameras-{Key}", + $"/device/{device.Key}", + cameras2 + ); + AddDefaultDeviceMessenger(messenger); + messengerAdded = true; + } + this.LogVerbose("Trying to cast to generic device for device: {key}", device.Key); if (device is EssentialsDevice) diff --git a/src/PepperDash.Essentials/ControlSystem.cs b/src/PepperDash.Essentials/ControlSystem.cs index b2fe1e19..28864e83 100644 --- a/src/PepperDash.Essentials/ControlSystem.cs +++ b/src/PepperDash.Essentials/ControlSystem.cs @@ -39,8 +39,6 @@ namespace PepperDash.Essentials DeviceManager.Initialize(this); SecretsManager.Initialize(); SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true; - - Debug.SetErrorLogMinimumDebugLevel(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? LogEventLevel.Warning : LogEventLevel.Verbose); } /// @@ -75,8 +73,6 @@ namespace PepperDash.Essentials private void StartSystem(object preventInitialization) { - Debug.SetErrorLogMinimumDebugLevel(LogEventLevel.Verbose); - DeterminePlatform(); if (Debug.DoNotLoadConfigOnNextBoot)