mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-06 16:25:01 +00:00
reorganizing devices folder
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PepperDash.Essentials.Core.Devices.Codec;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Devices.AudioCodec
|
||||
{
|
||||
public abstract class AudioCodecBase : EssentialsDevice, IHasDialer, IUsageTracking, IAudioCodecInfo
|
||||
{
|
||||
|
||||
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
|
||||
|
||||
public AudioCodecInfo CodecInfo { get; protected set; }
|
||||
|
||||
#region IUsageTracking Members
|
||||
|
||||
/// <summary>
|
||||
/// This object can be added by outside users of this class to provide usage tracking
|
||||
/// for various services
|
||||
/// </summary>
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns true when any call is not in state Unknown, Disconnecting, Disconnected
|
||||
/// </summary>
|
||||
public bool IsInCall
|
||||
{
|
||||
get
|
||||
{
|
||||
bool value;
|
||||
|
||||
if (ActiveCalls != null)
|
||||
value = ActiveCalls.Any(c => c.IsActiveCall);
|
||||
else
|
||||
value = false;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// In most cases only a single call can be active
|
||||
public List<CodecActiveCallItem> ActiveCalls { get; set; }
|
||||
|
||||
public AudioCodecBase(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
ActiveCalls = new List<CodecActiveCallItem>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to fire CallStatusChange event with old and new status
|
||||
/// </summary>
|
||||
protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatus, CodecActiveCallItem call)
|
||||
{
|
||||
call.Status = newStatus;
|
||||
|
||||
OnCallStatusChange(call);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="previousStatus"></param>
|
||||
/// <param name="newStatus"></param>
|
||||
/// <param name="item"></param>
|
||||
protected void OnCallStatusChange(CodecActiveCallItem item)
|
||||
{
|
||||
var handler = CallStatusChange;
|
||||
if (handler != null)
|
||||
handler(this, new CodecCallStatusItemChangeEventArgs(item));
|
||||
|
||||
if (UsageTracker != null)
|
||||
{
|
||||
if (IsInCall && !UsageTracker.UsageTrackingStarted)
|
||||
UsageTracker.StartDeviceUsage();
|
||||
else if (UsageTracker.UsageTrackingStarted && !IsInCall)
|
||||
UsageTracker.EndDeviceUsage();
|
||||
}
|
||||
}
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Devices
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for all Device APIs
|
||||
/// </summary>
|
||||
public abstract class DeviceApiBase
|
||||
{
|
||||
public Dictionary<string, Object> ActionApi { get; protected set; }
|
||||
public Dictionary<string, Feedback> FeedbackApi { get; protected set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public class DeviceJsonApi
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="json"></param>
|
||||
public static void DoDeviceActionWithJson(string json)
|
||||
{
|
||||
var action = JsonConvert.DeserializeObject<DeviceActionWrapper>(json);
|
||||
DoDeviceAction(action);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
public static void DoDeviceAction(DeviceActionWrapper action)
|
||||
{
|
||||
var key = action.DeviceKey;
|
||||
var obj = FindObjectOnPath(key);
|
||||
if (obj == null)
|
||||
return;
|
||||
|
||||
CType t = obj.GetType();
|
||||
var method = t.GetMethod(action.MethodName);
|
||||
if (method == null)
|
||||
{
|
||||
Debug.Console(0, "Method '{0}' not found", action.MethodName);
|
||||
return;
|
||||
}
|
||||
var mParams = method.GetParameters();
|
||||
// Add empty params if not provided
|
||||
if (action.Params == null) action.Params = new object[0];
|
||||
if (mParams.Length > action.Params.Length)
|
||||
{
|
||||
Debug.Console(0, "Method '{0}' requires {1} params", action.MethodName, mParams.Length);
|
||||
return;
|
||||
}
|
||||
object[] convertedParams = mParams
|
||||
.Select((p, i) => Convert.ChangeType(action.Params[i], p.ParameterType,
|
||||
System.Globalization.CultureInfo.InvariantCulture))
|
||||
.ToArray();
|
||||
object ret = method.Invoke(obj, convertedParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the properties on a device
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetProperties(string deviceObjectPath)
|
||||
{
|
||||
var obj = FindObjectOnPath(deviceObjectPath);
|
||||
if (obj == null)
|
||||
return "{ \"error\":\"No Device\"}";
|
||||
|
||||
CType t = obj.GetType();
|
||||
// get the properties and set them into a new collection of NameType wrappers
|
||||
var props = t.GetProperties().Select(p => new PropertyNameType(p, obj));
|
||||
return JsonConvert.SerializeObject(props, Formatting.Indented);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a property from a device path by name
|
||||
/// </summary>
|
||||
/// <param name="deviceObjectPath"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <returns></returns>
|
||||
public static object GetPropertyByName(string deviceObjectPath, string propertyName)
|
||||
{
|
||||
var obj = FindObjectOnPath(deviceObjectPath);
|
||||
if(obj == null)
|
||||
return "{ \"error\":\"No Device\"}";
|
||||
|
||||
CType t = obj.GetType();
|
||||
|
||||
var prop = t.GetProperty(propertyName);
|
||||
if (prop != null)
|
||||
{
|
||||
return prop;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, "Unable to find Property: {0} on Device with path: {1}", propertyName, deviceObjectPath);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the methods on a device
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetMethods(string deviceObjectPath)
|
||||
{
|
||||
var obj = FindObjectOnPath(deviceObjectPath);
|
||||
if (obj == null)
|
||||
return "{ \"error\":\"No Device\"}";
|
||||
|
||||
// Package up method names using helper objects
|
||||
CType t = obj.GetType();
|
||||
var methods = t.GetMethods()
|
||||
.Where(m => !m.IsSpecialName)
|
||||
.Select(p => new MethodNameParams(p));
|
||||
return JsonConvert.SerializeObject(methods, Formatting.Indented);
|
||||
}
|
||||
|
||||
public static string GetApiMethods(string deviceObjectPath)
|
||||
{
|
||||
var obj = FindObjectOnPath(deviceObjectPath);
|
||||
if (obj == null)
|
||||
return "{ \"error\":\"No Device\"}";
|
||||
|
||||
// Package up method names using helper objects
|
||||
CType t = obj.GetType();
|
||||
var methods = t.GetMethods()
|
||||
.Where(m => !m.IsSpecialName)
|
||||
.Where(m => m.GetCustomAttributes(typeof(ApiAttribute), true).Any())
|
||||
.Select(p => new MethodNameParams(p));
|
||||
return JsonConvert.SerializeObject(methods, Formatting.Indented);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Walks down a dotted object path, starting with a Device, and returns the object
|
||||
/// at the end of the path
|
||||
/// </summary>
|
||||
public static object FindObjectOnPath(string deviceObjectPath)
|
||||
{
|
||||
var path = deviceObjectPath.Split('.');
|
||||
|
||||
var dev = DeviceManager.GetDeviceForKey(path[0]);
|
||||
if (dev == null)
|
||||
{
|
||||
Debug.Console(0, "Device {0} not found", path[0]);
|
||||
return null;
|
||||
}
|
||||
|
||||
// loop through any dotted properties
|
||||
object obj = dev;
|
||||
if (path.Length > 1)
|
||||
{
|
||||
for (int i = 1; i < path.Length; i++)
|
||||
{
|
||||
var objName = path[i];
|
||||
string indexStr = null;
|
||||
var indexOpen = objName.IndexOf('[');
|
||||
if (indexOpen != -1)
|
||||
{
|
||||
var indexClose = objName.IndexOf(']');
|
||||
if (indexClose == -1)
|
||||
{
|
||||
Debug.Console(0, dev, "ERROR Unmatched index brackets");
|
||||
return null;
|
||||
}
|
||||
// Get the index and strip quotes if any
|
||||
indexStr = objName.Substring(indexOpen + 1, indexClose - indexOpen - 1).Replace("\"", "");
|
||||
objName = objName.Substring(0, indexOpen);
|
||||
Debug.Console(0, dev, " Checking for collection '{0}', index '{1}'", objName, indexStr);
|
||||
}
|
||||
|
||||
CType oType = obj.GetType();
|
||||
var prop = oType.GetProperty(objName);
|
||||
if (prop == null)
|
||||
{
|
||||
Debug.Console(0, dev, "Property {0} not found on {1}", objName, path[i - 1]);
|
||||
return null;
|
||||
}
|
||||
// if there's an index, try to get the property
|
||||
if (indexStr != null)
|
||||
{
|
||||
if (!typeof(ICollection).IsAssignableFrom(prop.PropertyType))
|
||||
{
|
||||
Debug.Console(0, dev, "Property {0} is not collection", objName);
|
||||
return null;
|
||||
}
|
||||
var collection = prop.GetValue(obj, null) as ICollection;
|
||||
// Get the indexed items "property"
|
||||
var indexedPropInfo = prop.PropertyType.GetProperty("Item");
|
||||
// These are the parameters for the indexing. Only care about one
|
||||
var indexParams = indexedPropInfo.GetIndexParameters();
|
||||
if (indexParams.Length > 0)
|
||||
{
|
||||
Debug.Console(0, " Indexed, param type: {0}", indexParams[0].ParameterType.Name);
|
||||
var properParam = Convert.ChangeType(indexStr, indexParams[0].ParameterType,
|
||||
System.Globalization.CultureInfo.InvariantCulture);
|
||||
try
|
||||
{
|
||||
obj = indexedPropInfo.GetValue(collection, new object[] { properParam });
|
||||
}
|
||||
// if the index is bad, catch it here.
|
||||
catch (Crestron.SimplSharp.Reflection.TargetInvocationException e)
|
||||
{
|
||||
if (e.InnerException is ArgumentOutOfRangeException)
|
||||
Debug.Console(0, " Index Out of range");
|
||||
else if (e.InnerException is KeyNotFoundException)
|
||||
Debug.Console(0, " Key not found");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
obj = prop.GetValue(obj, null);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a property on an object.
|
||||
/// </summary>
|
||||
/// <param name="deviceObjectPath"></param>
|
||||
/// <returns></returns>
|
||||
public static string SetProperty(string deviceObjectPath)
|
||||
{
|
||||
throw new NotImplementedException("This could be really useful. Finish it please");
|
||||
|
||||
//var obj = FindObjectOnPath(deviceObjectPath);
|
||||
//if (obj == null)
|
||||
// return "{\"error\":\"No object found\"}";
|
||||
|
||||
//CType t = obj.GetType();
|
||||
|
||||
|
||||
//// get the properties and set them into a new collection of NameType wrappers
|
||||
//var props = t.GetProperties().Select(p => new PropertyNameType(p, obj));
|
||||
//return JsonConvert.SerializeObject(props, Formatting.Indented);
|
||||
}
|
||||
}
|
||||
|
||||
public class DeviceActionWrapper
|
||||
{
|
||||
public string DeviceKey { get; set; }
|
||||
public string MethodName { get; set; }
|
||||
public object[] Params { get; set; }
|
||||
}
|
||||
|
||||
public class PropertyNameType
|
||||
{
|
||||
object Parent;
|
||||
|
||||
[JsonIgnore]
|
||||
public PropertyInfo PropInfo { get; private set; }
|
||||
public string Name { get { return PropInfo.Name; } }
|
||||
public string Type { get { return PropInfo.PropertyType.Name; } }
|
||||
public string Value { get
|
||||
{
|
||||
if (PropInfo.CanRead)
|
||||
{
|
||||
try
|
||||
{
|
||||
return PropInfo.GetValue(Parent, null).ToString();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
return null;
|
||||
} }
|
||||
|
||||
public bool CanRead { get { return PropInfo.CanRead; } }
|
||||
public bool CanWrite { get { return PropInfo.CanWrite; } }
|
||||
|
||||
|
||||
public PropertyNameType(PropertyInfo info, object parent)
|
||||
{
|
||||
PropInfo = info;
|
||||
Parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodNameParams
|
||||
{
|
||||
[JsonIgnore]
|
||||
public MethodInfo MethodInfo { get; private set; }
|
||||
|
||||
public string Name { get { return MethodInfo.Name; } }
|
||||
public IEnumerable<NameType> Params { get {
|
||||
return MethodInfo.GetParameters().Select(p =>
|
||||
new NameType { Name = p.Name, Type = p.ParameterType.Name });
|
||||
} }
|
||||
|
||||
public MethodNameParams(MethodInfo info)
|
||||
{
|
||||
MethodInfo = info;
|
||||
}
|
||||
}
|
||||
|
||||
public class NameType
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class ApiAttribute : CAttribute
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using PepperDash.Essentials.Core.Bridges;
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public abstract class EssentialsBridgeableDevice:EssentialsDevice, IBridgeAdvanced
|
||||
{
|
||||
protected EssentialsBridgeableDevice(string key) : base(key)
|
||||
{
|
||||
}
|
||||
|
||||
protected EssentialsBridgeableDevice(string key, string name) : base(key, name)
|
||||
{
|
||||
}
|
||||
|
||||
public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the basic needs for an EssentialsDevice to enable it to be build by an IDeviceFactory class
|
||||
/// </summary>
|
||||
[Description("The base Essentials Device Class")]
|
||||
public abstract class EssentialsDevice : Device
|
||||
{
|
||||
protected EssentialsDevice(string key)
|
||||
: base(key)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected EssentialsDevice(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
|
||||
public class DescriptionAttribute : Attribute
|
||||
{
|
||||
private string _Description;
|
||||
|
||||
public DescriptionAttribute(string description)
|
||||
{
|
||||
Debug.Console(2, "Setting Description: {0}", description);
|
||||
_Description = description;
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get { return _Description; }
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
|
||||
public class ConfigSnippetAttribute : Attribute
|
||||
{
|
||||
private string _ConfigSnippet;
|
||||
|
||||
public ConfigSnippetAttribute(string configSnippet)
|
||||
{
|
||||
Debug.Console(2, "Setting Config Snippet {0}", configSnippet);
|
||||
_ConfigSnippet = configSnippet;
|
||||
}
|
||||
|
||||
public string ConfigSnippet
|
||||
{
|
||||
get { return _ConfigSnippet; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devices the basic needs for a Device Factory
|
||||
/// </summary>
|
||||
public abstract class EssentialsDeviceFactory<T> : IDeviceFactory where T:EssentialsDevice
|
||||
{
|
||||
#region IDeviceFactory Members
|
||||
|
||||
/// <summary>
|
||||
/// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device
|
||||
/// </summary>
|
||||
public List<string> TypeNames { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Loads an item to the DeviceFactory.FactoryMethods dictionary for each entry in the TypeNames list
|
||||
/// </summary>
|
||||
public void LoadTypeFactories()
|
||||
{
|
||||
foreach (var typeName in TypeNames)
|
||||
{
|
||||
Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName);
|
||||
var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[];
|
||||
string description = descriptionAttribute[0].Description;
|
||||
var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[];
|
||||
DeviceFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildDevice);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The method that will build the device
|
||||
/// </summary>
|
||||
/// <param name="dc">The device config</param>
|
||||
/// <returns>An instance of the device</returns>
|
||||
public abstract EssentialsDevice BuildDevice(DeviceConfig dc);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devices the basic needs for a Device Factory
|
||||
/// </summary>
|
||||
public abstract class EssentialsPluginDeviceFactory<T> : EssentialsDeviceFactory<T>, IPluginDeviceFactory where T : EssentialsDevice
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33")
|
||||
/// </summary>
|
||||
public string MinimumEssentialsFrameworkVersion { get; protected set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Bridges;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Devices
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class ReconfigurableDevice : EssentialsDevice
|
||||
{
|
||||
public event EventHandler<EventArgs> ConfigChanged;
|
||||
|
||||
public DeviceConfig Config { get; private set; }
|
||||
|
||||
protected ReconfigurableDevice(DeviceConfig config)
|
||||
: base(config.Key)
|
||||
{
|
||||
SetNameHelper(config);
|
||||
|
||||
Config = config;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the Config, calls CustomSetConfig and fires the ConfigChanged event
|
||||
/// </summary>
|
||||
/// <param name="config"></param>
|
||||
public void SetConfig(DeviceConfig config)
|
||||
{
|
||||
Config = config;
|
||||
|
||||
SetNameHelper(config);
|
||||
|
||||
CustomSetConfig(config);
|
||||
|
||||
var handler = ConfigChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
void SetNameHelper(DeviceConfig config)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(config.Name))
|
||||
Name = config.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc)
|
||||
/// </summary>
|
||||
/// <param name="Config"></param>
|
||||
protected virtual void CustomSetConfig(DeviceConfig config)
|
||||
{
|
||||
ConfigWriter.UpdateDeviceConfig(config);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ReconfigurableBridgableDevice : ReconfigurableDevice, IBridgeAdvanced
|
||||
{
|
||||
protected ReconfigurableBridgableDevice(DeviceConfig config) : base(config)
|
||||
{
|
||||
}
|
||||
|
||||
public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public class SmartObjectJoinOffsets
|
||||
{
|
||||
public const ushort Dpad = 1;
|
||||
public const ushort Numpad = 2;
|
||||
|
||||
public const ushort PresetList = 6;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
using PepperDash.Essentials.Core.Devices.Codec;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Devices.VideoCodec
|
||||
{
|
||||
public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs,
|
||||
IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Fires when the status of any active, dialing, or incoming call changes or is new
|
||||
/// </summary>
|
||||
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
|
||||
|
||||
public event EventHandler<EventArgs> IsReadyChange;
|
||||
|
||||
public IBasicCommunication Communication { get; protected set; }
|
||||
|
||||
#region IUsageTracking Members
|
||||
|
||||
/// <summary>
|
||||
/// This object can be added by outside users of this class to provide usage tracking
|
||||
/// for various services
|
||||
/// </summary>
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// An internal pseudo-source that is routable and connected to the osd input
|
||||
/// </summary>
|
||||
public DummyRoutingInputsDevice OsdSource { get; protected set; }
|
||||
|
||||
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
|
||||
|
||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true when any call is not in state Unknown, Disconnecting, Disconnected
|
||||
/// </summary>
|
||||
public bool IsInCall
|
||||
{
|
||||
get
|
||||
{
|
||||
bool value;
|
||||
|
||||
if (ActiveCalls != null)
|
||||
value = ActiveCalls.Any(c => c.IsActiveCall);
|
||||
else
|
||||
value = false;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public BoolFeedback StandbyIsOnFeedback { get; private set; }
|
||||
|
||||
abstract protected Func<bool> PrivacyModeIsOnFeedbackFunc { get; }
|
||||
abstract protected Func<int> VolumeLevelFeedbackFunc { get; }
|
||||
abstract protected Func<bool> MuteFeedbackFunc { get; }
|
||||
abstract protected Func<bool> StandbyIsOnFeedbackFunc { get; }
|
||||
|
||||
public List<CodecActiveCallItem> ActiveCalls { get; set; }
|
||||
|
||||
public VideoCodecInfo CodecInfo { get; protected set; }
|
||||
|
||||
public bool ShowSelfViewByDefault { get; protected set; }
|
||||
|
||||
|
||||
public bool IsReady { get; protected set; }
|
||||
|
||||
public 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);
|
||||
|
||||
InputPorts = new RoutingPortCollection<RoutingInputPort>();
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
|
||||
|
||||
ActiveCalls = new List<CodecActiveCallItem>();
|
||||
}
|
||||
|
||||
#region IHasDialer Members
|
||||
|
||||
public abstract void Dial(string number);
|
||||
public abstract void Dial(Meeting meeting);
|
||||
public virtual void Dial(IInvitableContact contact)
|
||||
{
|
||||
|
||||
}
|
||||
public abstract void EndCall(CodecActiveCallItem call);
|
||||
public abstract void EndAllCalls();
|
||||
public abstract void AcceptCall(CodecActiveCallItem call);
|
||||
public abstract void RejectCall(CodecActiveCallItem call);
|
||||
public abstract void SendDtmf(string s);
|
||||
|
||||
#endregion
|
||||
|
||||
public virtual List<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<Feedback>
|
||||
{
|
||||
PrivacyModeIsOnFeedback,
|
||||
SharingSourceFeedback
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void ExecuteSwitch(object selector);
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to fire CallStatusChange event with old and new status
|
||||
/// </summary>
|
||||
protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatus, CodecActiveCallItem call)
|
||||
{
|
||||
call.Status = newStatus;
|
||||
|
||||
OnCallStatusChange(call);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="previousStatus"></param>
|
||||
/// <param name="newStatus"></param>
|
||||
/// <param name="item"></param>
|
||||
protected void OnCallStatusChange(CodecActiveCallItem item)
|
||||
{
|
||||
var handler = CallStatusChange;
|
||||
if (handler != null)
|
||||
handler(this, new CodecCallStatusItemChangeEventArgs(item));
|
||||
|
||||
if (AutoShareContentWhileInCall)
|
||||
StartSharing();
|
||||
|
||||
if (UsageTracker != null)
|
||||
{
|
||||
if (IsInCall && !UsageTracker.UsageTrackingStarted)
|
||||
UsageTracker.StartDeviceUsage();
|
||||
else if (UsageTracker.UsageTrackingStarted && !IsInCall)
|
||||
UsageTracker.EndDeviceUsage();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets IsReady property and fires the event. Used for dependent classes to sync up their data.
|
||||
/// </summary>
|
||||
protected void SetIsReady()
|
||||
{
|
||||
IsReady = true;
|
||||
var h = IsReadyChange;
|
||||
if(h != null)
|
||||
h(this, new EventArgs());
|
||||
}
|
||||
|
||||
#region ICodecAudio Members
|
||||
|
||||
public abstract void PrivacyModeOn();
|
||||
public abstract void PrivacyModeOff();
|
||||
public abstract void PrivacyModeToggle();
|
||||
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
|
||||
|
||||
|
||||
public BoolFeedback MuteFeedback { get; private set; }
|
||||
|
||||
public abstract void MuteOff();
|
||||
|
||||
public abstract void MuteOn();
|
||||
|
||||
public abstract void SetVolume(ushort level);
|
||||
|
||||
public IntFeedback VolumeLevelFeedback { get; private set; }
|
||||
|
||||
public abstract void MuteToggle();
|
||||
|
||||
public abstract void VolumeDown(bool pressRelease);
|
||||
|
||||
|
||||
public abstract void VolumeUp(bool pressRelease);
|
||||
|
||||
#endregion
|
||||
|
||||
#region IHasSharing Members
|
||||
|
||||
public abstract void StartSharing();
|
||||
public abstract void StopSharing();
|
||||
|
||||
public bool AutoShareContentWhileInCall { get; protected set; }
|
||||
|
||||
public StringFeedback SharingSourceFeedback { get; private set; }
|
||||
public BoolFeedback SharingContentIsOnFeedback { get; private set; }
|
||||
|
||||
abstract protected Func<string> SharingSourceFeedbackFunc { get; }
|
||||
abstract protected Func<bool> SharingContentIsOnFeedbackFunc { get; }
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
// **** DEBUGGING THINGS ****
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public virtual void ListCalls()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var c in ActiveCalls)
|
||||
sb.AppendFormat("{0} {1} -- {2} {3}\n", c.Id, c.Number, c.Name, c.Status);
|
||||
Debug.Console(1, this, "\n{0}\n", sb.ToString());
|
||||
}
|
||||
|
||||
public abstract void StandbyActivate();
|
||||
|
||||
public abstract void StandbyDeactivate();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Used to track the status of syncronizing the phonebook values when connecting to a codec or refreshing the phonebook info
|
||||
/// </summary>
|
||||
public class CodecPhonebookSyncState : IKeyed
|
||||
{
|
||||
bool _InitialSyncComplete;
|
||||
|
||||
public event EventHandler<EventArgs> InitialSyncCompleted;
|
||||
|
||||
public string Key { get; private set; }
|
||||
|
||||
public bool InitialSyncComplete
|
||||
{
|
||||
get { return _InitialSyncComplete; }
|
||||
private set
|
||||
{
|
||||
if (value == true)
|
||||
{
|
||||
var handler = InitialSyncCompleted;
|
||||
if (handler != null)
|
||||
handler(this, new EventArgs());
|
||||
}
|
||||
_InitialSyncComplete = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool InitialPhonebookFoldersWasReceived { get; private set; }
|
||||
|
||||
public bool NumberOfContactsWasReceived { get; private set; }
|
||||
|
||||
public bool PhonebookRootEntriesWasRecieved { get; private set; }
|
||||
|
||||
public bool PhonebookHasFolders { get; private set; }
|
||||
|
||||
public int NumberOfContacts { get; private set; }
|
||||
|
||||
public CodecPhonebookSyncState(string key)
|
||||
{
|
||||
Key = key;
|
||||
|
||||
CodecDisconnected();
|
||||
}
|
||||
|
||||
public void InitialPhonebookFoldersReceived()
|
||||
{
|
||||
InitialPhonebookFoldersWasReceived = true;
|
||||
|
||||
CheckSyncStatus();
|
||||
}
|
||||
|
||||
public void PhonebookRootEntriesReceived()
|
||||
{
|
||||
PhonebookRootEntriesWasRecieved = true;
|
||||
|
||||
CheckSyncStatus();
|
||||
}
|
||||
|
||||
public void SetPhonebookHasFolders(bool value)
|
||||
{
|
||||
PhonebookHasFolders = value;
|
||||
|
||||
Debug.Console(1, this, "Phonebook has folders: {0}", PhonebookHasFolders);
|
||||
}
|
||||
|
||||
public void SetNumberOfContacts(int contacts)
|
||||
{
|
||||
NumberOfContacts = contacts;
|
||||
NumberOfContactsWasReceived = true;
|
||||
|
||||
Debug.Console(1, this, "Phonebook contains {0} contacts.", NumberOfContacts);
|
||||
|
||||
CheckSyncStatus();
|
||||
}
|
||||
|
||||
public void CodecDisconnected()
|
||||
{
|
||||
InitialPhonebookFoldersWasReceived = false;
|
||||
PhonebookHasFolders = false;
|
||||
NumberOfContacts = 0;
|
||||
NumberOfContactsWasReceived = false;
|
||||
}
|
||||
|
||||
void CheckSyncStatus()
|
||||
{
|
||||
if (InitialPhonebookFoldersWasReceived && NumberOfContactsWasReceived && PhonebookRootEntriesWasRecieved)
|
||||
{
|
||||
InitialSyncComplete = true;
|
||||
Debug.Console(1, this, "Initial Phonebook Sync Complete!");
|
||||
}
|
||||
else
|
||||
InitialSyncComplete = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user