mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-07-02 10:38:16 +00:00
feat: Add messengers for codec functionalities and directory management
- Implemented IHasCodecCamerasMessenger to handle camera selection and control actions. - Created IHasCodecLayoutsMessenger for managing codec layouts. - Developed IHasCodecSelfViewMessenger to manage self-view functionality. - Added IHasDirectoryMessenger for directory operations including fetching and searching. - Introduced IHasFarEndContentStatusMessenger to report far-end content status. - Implemented IPasswordPromptMessenger for handling password prompts. - Updated VideoCodecBaseMessenger to remove redundant directory and call history handling. - Registered new messenger types in MessengerFactoryRegistry. - Added necessary using directives in ControlSystem.cs for UC functionalities. Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
parent
e19e69d5c0
commit
ab4a243ffb
12 changed files with 845 additions and 643 deletions
|
|
@ -1,11 +1,8 @@
|
|||
|
||||
|
||||
using System;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Config;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Messenger for devices implementing <see cref="IHasCallHistory"/>
|
||||
/// </summary>
|
||||
public class IHasCallHistoryMessenger : MessengerBase
|
||||
{
|
||||
private readonly IHasCallHistory _callHistory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IHasCallHistoryMessenger"/> class.
|
||||
/// </summary>
|
||||
public IHasCallHistoryMessenger(string key, string messagePath, EssentialsDevice device)
|
||||
: base(key, messagePath, device)
|
||||
{
|
||||
_callHistory = device as IHasCallHistory ?? throw new ArgumentException("device must implement IHasCallHistory", nameof(device));
|
||||
_callHistory.CallHistory.RecentCallsListHasChanged += CallHistory_RecentCallsListHasChanged;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
AddAction("/fullStatus", (id, content) => PostCallHistory());
|
||||
|
||||
AddAction("/getCallHistory", (id, content) => PostCallHistory());
|
||||
}
|
||||
|
||||
private void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(sender is CodecCallHistory codecCallHistory)) return;
|
||||
|
||||
var recents = codecCallHistory.RecentCalls;
|
||||
if (recents != null)
|
||||
{
|
||||
PostStatusMessage(new IHasCallHistoryStateMessage
|
||||
{
|
||||
RecentCalls = recents
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting call history");
|
||||
}
|
||||
}
|
||||
|
||||
private void PostCallHistory()
|
||||
{
|
||||
try
|
||||
{
|
||||
var recents = _callHistory.CallHistory.RecentCalls;
|
||||
if (recents != null)
|
||||
{
|
||||
PostStatusMessage(new IHasCallHistoryStateMessage
|
||||
{
|
||||
RecentCalls = recents
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting call history");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class IHasCallHistoryStateMessage : DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("recentCalls", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public List<CodecCallHistory.CallHistoryEntry> RecentCalls { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
/// <summary>
|
||||
/// Messenger for devices that implement the IHasCameras interface.
|
||||
/// </summary>
|
||||
public class IHasCamerasWithControlMessenger : MessengerBase
|
||||
public class IHasCamerasWithControlsMessenger : MessengerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Device being bridged that implements IHasCameras interface.
|
||||
|
|
@ -26,7 +26,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
/// <param name="cameraController"></param>
|
||||
/// <param name="messagePath"></param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public IHasCamerasWithControlMessenger(string key, string messagePath, IHasCamerasWithControls cameraController)
|
||||
public IHasCamerasWithControlsMessenger(string key, string messagePath, IHasCamerasWithControls cameraController)
|
||||
: base(key, messagePath, cameraController)
|
||||
{
|
||||
CameraController = cameraController ?? throw new ArgumentNullException("cameraController");
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Cameras;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Messenger for devices implementing <see cref="IHasCodecCameras"/>, including
|
||||
/// sub-interface support for <see cref="IHasCodecRoomPresets"/>,
|
||||
/// <see cref="IHasCameraAutoMode"/>, and <see cref="IHasCameraOff"/>.
|
||||
/// </summary>
|
||||
public class IHasCodecCamerasMessenger : MessengerBase
|
||||
{
|
||||
private readonly VideoCodecBase _codec;
|
||||
private readonly IHasCodecCameras _cameraCodec;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IHasCodecCamerasMessenger"/> class.
|
||||
/// </summary>
|
||||
public IHasCodecCamerasMessenger(string key, string messagePath, VideoCodecBase codec)
|
||||
: base(key, messagePath, codec)
|
||||
{
|
||||
_codec = codec ?? throw new ArgumentNullException(nameof(codec));
|
||||
_cameraCodec = codec as IHasCodecCameras ?? throw new ArgumentException("codec must implement IHasCodecCameras", nameof(codec));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
this.LogVerbose("Adding IHasCodecCameras Actions");
|
||||
|
||||
_cameraCodec.CameraSelected += CameraCodec_CameraSelected;
|
||||
|
||||
AddAction("/fullStatus", (id, content) => PostSelectedCamera());
|
||||
|
||||
AddAction("/cameraSelect", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
_cameraCodec.SelectCamera(msg.Value);
|
||||
});
|
||||
|
||||
MapCameraActions();
|
||||
|
||||
if (_codec is IHasCodecRoomPresets presetsCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IHasCodecRoomPresets Actions");
|
||||
|
||||
presetsCodec.CodecRoomPresetsListHasChanged += PresetsCodec_CameraPresetsListHasChanged;
|
||||
|
||||
AddAction("/cameraPreset", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<int>>();
|
||||
presetsCodec.CodecRoomPresetSelect(msg.Value);
|
||||
});
|
||||
|
||||
AddAction("/cameraPresetStore", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<CodecRoomPreset>();
|
||||
presetsCodec.CodecRoomPresetStore(msg.ID, msg.Description);
|
||||
});
|
||||
}
|
||||
|
||||
if (_codec is IHasCameraAutoMode speakerTrackCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IHasCameraAutoMode Actions");
|
||||
|
||||
speakerTrackCodec.CameraAutoModeIsOnFeedback.OutputChange += CameraAutoModeIsOnFeedback_OutputChange;
|
||||
|
||||
AddAction("/cameraModeAuto", (id, content) => speakerTrackCodec.CameraAutoModeOn());
|
||||
AddAction("/cameraModeManual", (id, content) => speakerTrackCodec.CameraAutoModeOff());
|
||||
}
|
||||
|
||||
if (_codec is IHasCameraOff cameraOffCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IHasCameraOff Actions");
|
||||
|
||||
cameraOffCodec.CameraIsOffFeedback.OutputChange += CameraIsOffFeedback_OutputChange;
|
||||
|
||||
AddAction("/cameraModeOff", (id, content) => cameraOffCodec.CameraOff());
|
||||
}
|
||||
}
|
||||
|
||||
private void CameraCodec_CameraSelected(object sender, CameraSelectedEventArgs<IHasCameraControls> e)
|
||||
{
|
||||
try
|
||||
{
|
||||
MapCameraActions();
|
||||
PostSelectedCamera();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Exception handling camera selected event");
|
||||
}
|
||||
}
|
||||
|
||||
private void MapCameraActions()
|
||||
{
|
||||
if (_cameraCodec.SelectedCamera == null) return;
|
||||
|
||||
RemoveAction("/cameraUp");
|
||||
RemoveAction("/cameraDown");
|
||||
RemoveAction("/cameraLeft");
|
||||
RemoveAction("/cameraRight");
|
||||
RemoveAction("/cameraZoomIn");
|
||||
RemoveAction("/cameraZoomOut");
|
||||
RemoveAction("/cameraHome");
|
||||
|
||||
if (_cameraCodec.SelectedCamera is IHasCameraPtzControl camera)
|
||||
{
|
||||
AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, b =>
|
||||
{
|
||||
if (b) camera.TiltUp(); else camera.TiltStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, b =>
|
||||
{
|
||||
if (b) camera.TiltDown(); else camera.TiltStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, b =>
|
||||
{
|
||||
if (b) camera.PanLeft(); else camera.PanStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, b =>
|
||||
{
|
||||
if (b) camera.PanRight(); else camera.PanStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, b =>
|
||||
{
|
||||
if (b) camera.ZoomIn(); else camera.ZoomStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, b =>
|
||||
{
|
||||
if (b) camera.ZoomOut(); else camera.ZoomStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraHome", (id, content) => camera.PositionHome());
|
||||
|
||||
RemoveAction("/cameraAutoFocus");
|
||||
RemoveAction("/cameraFocusNear");
|
||||
RemoveAction("/cameraFocusFar");
|
||||
|
||||
if (_cameraCodec.SelectedCamera is IHasCameraFocusControl focusCamera)
|
||||
{
|
||||
AddAction("/cameraAutoFocus", (id, content) => focusCamera.TriggerAutoFocus());
|
||||
|
||||
AddAction("/cameraFocusNear", (id, content) => HandleCameraPressAndHold(content, b =>
|
||||
{
|
||||
if (b) focusCamera.FocusNear(); else focusCamera.FocusStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraFocusFar", (id, content) => HandleCameraPressAndHold(content, b =>
|
||||
{
|
||||
if (b) focusCamera.FocusFar(); else focusCamera.FocusStop();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
|
||||
{
|
||||
var state = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
|
||||
if (timerHandler == null) return;
|
||||
timerHandler(state.Value, cameraAction);
|
||||
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
private void CameraAutoModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||
{
|
||||
PostCameraMode();
|
||||
}
|
||||
|
||||
private void CameraIsOffFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||
{
|
||||
PostCameraMode();
|
||||
}
|
||||
|
||||
private void PresetsCodec_CameraPresetsListHasChanged(object sender, EventArgs e)
|
||||
{
|
||||
PostCameraPresets();
|
||||
}
|
||||
|
||||
private string GetCameraMode()
|
||||
{
|
||||
string m = "";
|
||||
|
||||
if (_codec is IHasCameraAutoMode speakerTrackCodec)
|
||||
{
|
||||
m = speakerTrackCodec.CameraAutoModeIsOnFeedback.BoolValue
|
||||
? eCameraControlMode.Auto.ToString().ToLower()
|
||||
: eCameraControlMode.Manual.ToString().ToLower();
|
||||
}
|
||||
|
||||
if (_codec is IHasCameraOff cameraOffCodec && cameraOffCodec.CameraIsOffFeedback.BoolValue)
|
||||
{
|
||||
m = eCameraControlMode.Off.ToString().ToLower();
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
private Camera GetSelectedCamera()
|
||||
{
|
||||
var camera = new Camera();
|
||||
|
||||
if (_cameraCodec.SelectedCameraFeedback != null)
|
||||
camera.Key = _cameraCodec.SelectedCameraFeedback.StringValue;
|
||||
|
||||
if (_cameraCodec.SelectedCamera != null)
|
||||
{
|
||||
camera.Name = _cameraCodec.SelectedCamera.Name;
|
||||
|
||||
if (_cameraCodec.SelectedCamera is IHasCameraPtzControl ptz)
|
||||
{
|
||||
camera.Capabilities = new CameraCapabilities
|
||||
{
|
||||
CanPan = ptz is IHasCameraPanControl,
|
||||
CanTilt = ptz is IHasCameraTiltControl,
|
||||
CanZoom = ptz is IHasCameraZoomControl,
|
||||
CanFocus = ptz is IHasCameraFocusControl,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (_cameraCodec.ControllingFarEndCameraFeedback != null)
|
||||
camera.IsFarEnd = _cameraCodec.ControllingFarEndCameraFeedback.BoolValue;
|
||||
|
||||
return camera;
|
||||
}
|
||||
|
||||
private List<CodecRoomPreset> GetCurrentPresets()
|
||||
{
|
||||
if (!(_codec is IHasCodecRoomPresets presetsCodec)) return null;
|
||||
|
||||
if (_codec is IHasFarEndCameraControl farEnd && farEnd.ControllingFarEndCameraFeedback.BoolValue)
|
||||
return presetsCodec.FarEndRoomPresets;
|
||||
|
||||
return presetsCodec.NearEndPresets;
|
||||
}
|
||||
|
||||
private void PostCameraMode()
|
||||
{
|
||||
try
|
||||
{
|
||||
PostStatusMessage(new IHasCodecCamerasStateMessage
|
||||
{
|
||||
CameraMode = GetCameraMode()
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting camera mode");
|
||||
}
|
||||
}
|
||||
|
||||
private void PostSelectedCamera()
|
||||
{
|
||||
try
|
||||
{
|
||||
PostStatusMessage(new IHasCodecCamerasStateMessage
|
||||
{
|
||||
Cameras = new CameraStatus { SelectedCamera = GetSelectedCamera() },
|
||||
Presets = GetCurrentPresets()
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting selected camera");
|
||||
}
|
||||
}
|
||||
|
||||
private void PostCameraPresets()
|
||||
{
|
||||
try
|
||||
{
|
||||
PostStatusMessage(new IHasCodecCamerasStateMessage
|
||||
{
|
||||
Presets = GetCurrentPresets()
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting camera presets");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class IHasCodecCamerasStateMessage : DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string CameraMode { get; set; }
|
||||
|
||||
[JsonProperty("cameras", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public CameraStatus Cameras { get; set; }
|
||||
|
||||
[JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public List<CodecRoomPreset> Presets { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Messenger for devices implementing <see cref="IHasCodecLayouts"/>
|
||||
/// </summary>
|
||||
public class IHasCodecLayoutsMessenger : MessengerBase
|
||||
{
|
||||
private readonly IHasCodecLayouts _layouts;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IHasCodecLayoutsMessenger"/> class.
|
||||
/// </summary>
|
||||
public IHasCodecLayoutsMessenger(string key, string messagePath, EssentialsDevice device)
|
||||
: base(key, messagePath, device)
|
||||
{
|
||||
_layouts = device as IHasCodecLayouts ?? throw new ArgumentException("device must implement IHasCodecLayouts", nameof(device));
|
||||
|
||||
_layouts.LocalLayoutFeedback.OutputChange += LocalLayoutFeedback_OutputChange;
|
||||
}
|
||||
|
||||
private void LocalLayoutFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||
{
|
||||
SendFullStatus();
|
||||
}
|
||||
|
||||
private void SendFullStatus()
|
||||
{
|
||||
PostStatusMessage(new IHasCodecLayoutsStateMessage
|
||||
{
|
||||
CurrentLayout = _layouts.LocalLayoutFeedback.StringValue
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
||||
|
||||
AddAction("/layoutStatus", (id, content) => SendFullStatus());
|
||||
|
||||
AddAction("/cameraRemoteView", (id, content) => _layouts.LocalLayoutToggle());
|
||||
AddAction("/cameraLayout", (id, content) => _layouts.LocalLayoutToggle());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// State message for <see cref="IHasCodecLayoutsMessenger"/>
|
||||
/// </summary>
|
||||
public class IHasCodecLayoutsStateMessage : DeviceStateMessageBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the current layout of the codec
|
||||
/// </summary>
|
||||
[JsonProperty("currentLayout", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string CurrentLayout { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Messenger for devices implementing <see cref="IHasCodecSelfView"/>
|
||||
/// </summary>
|
||||
public class IHasCodecSelfViewMessenger : MessengerBase
|
||||
{
|
||||
private readonly IHasCodecSelfView _selfView;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IHasCodecSelfViewMessenger"/> class.
|
||||
/// </summary>
|
||||
public IHasCodecSelfViewMessenger(string key, string messagePath, EssentialsDevice device)
|
||||
: base(key, messagePath, device)
|
||||
{
|
||||
_selfView = device as IHasCodecSelfView ?? throw new ArgumentException("device must implement IHasCodecSelfView", nameof(device));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
AddAction("/cameraSelfView", (id, content) => _selfView.SelfViewModeToggle());
|
||||
|
||||
_selfView.SelfviewIsOnFeedback.OutputChange += SelfviewIsOnFeedback_OutputChange;
|
||||
}
|
||||
|
||||
private void SelfviewIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||
{
|
||||
PostCameraSelfView();
|
||||
}
|
||||
|
||||
private void PostCameraSelfView()
|
||||
{
|
||||
try
|
||||
{
|
||||
PostStatusMessage(new IHasCodecSelfViewStateMessage
|
||||
{
|
||||
CameraSelfViewIsOn = _selfView.SelfviewIsOnFeedback.BoolValue
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting camera self view");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class IHasCodecSelfViewStateMessage : DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("cameraSelfView", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? CameraSelfViewIsOn { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Messenger for devices implementing <see cref="IHasDirectory"/>
|
||||
/// </summary>
|
||||
public class IHasDirectoryMessenger : MessengerBase
|
||||
{
|
||||
private readonly IHasDirectory _directory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IHasDirectoryMessenger"/> class.
|
||||
/// </summary>
|
||||
public IHasDirectoryMessenger(string key, string messagePath, EssentialsDevice device)
|
||||
: base(key, messagePath, device)
|
||||
{
|
||||
_directory = device as IHasDirectory ?? throw new ArgumentException("device must implement IHasDirectory", nameof(device));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
AddAction("/getDirectory", (id, content) => GetDirectoryRoot());
|
||||
|
||||
AddAction("/directoryById", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
GetDirectory(msg.Value);
|
||||
});
|
||||
|
||||
AddAction("/directorySearch", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
GetDirectory(msg.Value);
|
||||
});
|
||||
|
||||
AddAction("/directoryBack", (id, content) => GetPreviousDirectory());
|
||||
|
||||
_directory.DirectoryResultReturned += DirectoryResultReturned;
|
||||
_directory.PhonebookSyncState.InitialSyncCompleted += PhonebookSyncState_InitialSyncCompleted;
|
||||
}
|
||||
|
||||
private void DirectoryResultReturned(object sender, DirectoryEventArgs e)
|
||||
{
|
||||
SendDirectory(e.Directory);
|
||||
}
|
||||
|
||||
private void SendDirectory(CodecDirectory directory)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.LogVerbose("Sending Directory. Directory Item Count: {directoryItemCount}", directory.CurrentDirectoryResults.Count);
|
||||
Task.Run(() => PostStatusMessage(new IHasDirectoryStateMessage
|
||||
{
|
||||
CurrentDirectory = directory
|
||||
}));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error sending directory");
|
||||
}
|
||||
}
|
||||
|
||||
private void PhonebookSyncState_InitialSyncCompleted(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
PostStatusMessage(new IHasDirectoryStateMessage
|
||||
{
|
||||
InitialPhonebookSyncComplete = true
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting phonebook sync state");
|
||||
}
|
||||
}
|
||||
|
||||
private void GetDirectory(string id)
|
||||
{
|
||||
_directory.GetDirectoryFolderContents(id);
|
||||
}
|
||||
|
||||
private void GetDirectoryRoot()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_directory.PhonebookSyncState.InitialSyncComplete)
|
||||
{
|
||||
PostStatusMessage(new IHasDirectoryStateMessage
|
||||
{
|
||||
InitialPhonebookSyncComplete = false
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
_directory.SetCurrentDirectoryToRoot();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error getting directory root");
|
||||
}
|
||||
}
|
||||
|
||||
private void GetPreviousDirectory()
|
||||
{
|
||||
_directory.GetDirectoryParentFolderContents();
|
||||
}
|
||||
}
|
||||
|
||||
public class IHasDirectoryStateMessage : DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("currentDirectory", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public CodecDirectory CurrentDirectory { get; set; }
|
||||
|
||||
[JsonProperty("initialPhonebookSyncComplete", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? InitialPhonebookSyncComplete { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Messenger for devices implementing <see cref="IHasFarEndContentStatus"/>
|
||||
/// </summary>
|
||||
public class IHasFarEndContentStatusMessenger : MessengerBase
|
||||
{
|
||||
private readonly IHasFarEndContentStatus _device;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IHasFarEndContentStatusMessenger"/> class.
|
||||
/// </summary>
|
||||
public IHasFarEndContentStatusMessenger(string key, string messagePath, EssentialsDevice device)
|
||||
: base(key, messagePath, device)
|
||||
{
|
||||
_device = device as IHasFarEndContentStatus ?? throw new ArgumentException("device must implement IHasFarEndContentStatus", nameof(device));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
_device.ReceivingContent.OutputChange += (sender, args) => PostReceivingContent(args.BoolValue);
|
||||
}
|
||||
|
||||
private void PostReceivingContent(bool receivingContent)
|
||||
{
|
||||
try
|
||||
{
|
||||
PostStatusMessage(new IHasFarEndContentStatusStateMessage
|
||||
{
|
||||
ReceivingContent = receivingContent
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting receiving content");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class IHasFarEndContentStatusStateMessage : DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("receivingContent", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? ReceivingContent { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Messenger for devices implementing <see cref="IPasswordPrompt"/>
|
||||
/// </summary>
|
||||
public class IPasswordPromptMessenger : MessengerBase
|
||||
{
|
||||
private readonly IPasswordPrompt _device;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IPasswordPromptMessenger"/> class.
|
||||
/// </summary>
|
||||
public IPasswordPromptMessenger(string key, string messagePath, EssentialsDevice device)
|
||||
: base(key, messagePath, device)
|
||||
{
|
||||
_device = device as IPasswordPrompt ?? throw new ArgumentException("device must implement IPasswordPrompt", nameof(device));
|
||||
_device.PasswordRequired += OnPasswordRequired;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
AddAction("/password", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
_device.SubmitPassword(msg.Value);
|
||||
});
|
||||
}
|
||||
|
||||
private void OnPasswordRequired(object sender, PasswordPromptEventArgs args)
|
||||
{
|
||||
PostEventMessage(new PasswordPromptEventMessage
|
||||
{
|
||||
Message = args.Message,
|
||||
LastAttemptWasIncorrect = args.LastAttemptWasIncorrect,
|
||||
LoginAttemptFailed = args.LoginAttemptFailed,
|
||||
LoginAttemptCancelled = args.LoginAttemptCancelled,
|
||||
EventType = "passwordPrompt"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base event message for video codec events
|
||||
/// </summary>
|
||||
public class VideoCodecBaseEventMessage : DeviceEventMessageBase
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event message sent when a password is required
|
||||
/// </summary>
|
||||
public class PasswordPromptEventMessage : VideoCodecBaseEventMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Message
|
||||
/// </summary>
|
||||
[JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LastAttemptWasIncorrect
|
||||
/// </summary>
|
||||
[JsonProperty("lastAttemptWasIncorrect", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool LastAttemptWasIncorrect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LoginAttemptFailed
|
||||
/// </summary>
|
||||
[JsonProperty("loginAttemptFailed", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool LoginAttemptFailed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LoginAttemptCancelled
|
||||
/// </summary>
|
||||
[JsonProperty("loginAttemptCancelled", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool LoginAttemptCancelled { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -38,99 +38,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
Codec = codec ?? throw new ArgumentNullException("codec");
|
||||
codec.CallStatusChange += Codec_CallStatusChange;
|
||||
codec.IsReadyChange += Codec_IsReadyChange;
|
||||
|
||||
if (codec is IHasDirectory dirCodec)
|
||||
{
|
||||
dirCodec.DirectoryResultReturned += DirCodec_DirectoryResultReturned;
|
||||
}
|
||||
|
||||
if (codec is IHasCallHistory recCodec)
|
||||
{
|
||||
recCodec.CallHistory.RecentCallsListHasChanged += CallHistory_RecentCallsListHasChanged;
|
||||
}
|
||||
|
||||
if (codec is IPasswordPrompt pwPromptCodec)
|
||||
{
|
||||
pwPromptCodec.PasswordRequired += OnPasswordRequired;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPasswordRequired(object sender, PasswordPromptEventArgs args)
|
||||
{
|
||||
var eventMsg = new PasswordPromptEventMessage
|
||||
{
|
||||
Message = args.Message,
|
||||
LastAttemptWasIncorrect = args.LastAttemptWasIncorrect,
|
||||
LoginAttemptFailed = args.LoginAttemptFailed,
|
||||
LoginAttemptCancelled = args.LoginAttemptCancelled,
|
||||
EventType = "passwordPrompt"
|
||||
};
|
||||
|
||||
PostEventMessage(eventMsg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var state = new VideoCodecBaseStateMessage();
|
||||
|
||||
if (!(sender is CodecCallHistory codecCallHistory)) return;
|
||||
var recents = codecCallHistory.RecentCalls;
|
||||
|
||||
if (recents != null)
|
||||
{
|
||||
state.RecentCalls = recents;
|
||||
|
||||
PostStatusMessage(state);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting call history");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void DirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e)
|
||||
{
|
||||
if (Codec is IHasDirectory)
|
||||
SendDirectory(e.Directory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts the current directory
|
||||
/// </summary>
|
||||
protected void SendDirectory(CodecDirectory directory)
|
||||
{
|
||||
try
|
||||
{
|
||||
var state = new VideoCodecBaseStateMessage();
|
||||
|
||||
|
||||
if (Codec is IHasDirectory dirCodec)
|
||||
{
|
||||
this.LogVerbose("Sending Directory. Directory Item Count: {directoryItemCount}", directory.CurrentDirectoryResults.Count);
|
||||
|
||||
//state.CurrentDirectory = PrefixDirectoryFolderItems(directory);
|
||||
state.CurrentDirectory = directory;
|
||||
|
||||
Task.Run(() => PostStatusMessage(state));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error sending directory");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -217,132 +124,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
Codec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange;
|
||||
Codec.SharingSourceFeedback.OutputChange += SharingSourceFeedback_OutputChange;
|
||||
|
||||
// Directory actions
|
||||
if (Codec is IHasDirectory dirCodec)
|
||||
{
|
||||
AddAction("/getDirectory", (id, content) => GetDirectoryRoot());
|
||||
|
||||
AddAction("/directoryById", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
GetDirectory(msg.Value);
|
||||
});
|
||||
|
||||
AddAction("/directorySearch", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
|
||||
GetDirectory(msg.Value);
|
||||
});
|
||||
|
||||
AddAction("/directoryBack", (id, content) => GetPreviousDirectory());
|
||||
|
||||
dirCodec.PhonebookSyncState.InitialSyncCompleted += PhonebookSyncState_InitialSyncCompleted;
|
||||
}
|
||||
|
||||
// History actions
|
||||
if (Codec is IHasCallHistory recCodec)
|
||||
{
|
||||
AddAction("/getCallHistory", (id, content) => PostCallHistory());
|
||||
}
|
||||
if (Codec is IHasCodecCameras cameraCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IHasCodecCameras Actions");
|
||||
|
||||
cameraCodec.CameraSelected += CameraCodec_CameraSelected;
|
||||
|
||||
AddAction("/cameraSelect", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
|
||||
cameraCodec.SelectCamera(msg.Value);
|
||||
});
|
||||
|
||||
|
||||
MapCameraActions();
|
||||
|
||||
if (Codec is IHasCodecRoomPresets presetsCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IHasCodecRoomPresets Actions");
|
||||
|
||||
presetsCodec.CodecRoomPresetsListHasChanged += PresetsCodec_CameraPresetsListHasChanged;
|
||||
|
||||
AddAction("/cameraPreset", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<int>>();
|
||||
|
||||
presetsCodec.CodecRoomPresetSelect(msg.Value);
|
||||
});
|
||||
|
||||
AddAction("/cameraPresetStore", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<CodecRoomPreset>();
|
||||
|
||||
presetsCodec.CodecRoomPresetStore(msg.ID, msg.Description);
|
||||
});
|
||||
}
|
||||
|
||||
if (Codec is IHasCameraAutoMode speakerTrackCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IHasCameraAutoMode Actions");
|
||||
|
||||
speakerTrackCodec.CameraAutoModeIsOnFeedback.OutputChange += CameraAutoModeIsOnFeedback_OutputChange;
|
||||
|
||||
AddAction("/cameraModeAuto", (id, content) => speakerTrackCodec.CameraAutoModeOn());
|
||||
|
||||
AddAction("/cameraModeManual", (id, content) => speakerTrackCodec.CameraAutoModeOff());
|
||||
}
|
||||
|
||||
if (Codec is IHasCameraOff cameraOffCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IHasCameraOff Actions");
|
||||
|
||||
cameraOffCodec.CameraIsOffFeedback.OutputChange += (CameraIsOffFeedback_OutputChange);
|
||||
|
||||
AddAction("/cameraModeOff", (id, content) => cameraOffCodec.CameraOff());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (Codec is IHasCodecSelfView selfViewCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IHasCodecSelfView Actions");
|
||||
|
||||
AddAction("/cameraSelfView", (id, content) => selfViewCodec.SelfViewModeToggle());
|
||||
|
||||
selfViewCodec.SelfviewIsOnFeedback.OutputChange += new EventHandler<FeedbackEventArgs>(SelfviewIsOnFeedback_OutputChange);
|
||||
}
|
||||
|
||||
|
||||
if (Codec is IHasCodecLayouts layoutsCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IHasCodecLayouts Actions");
|
||||
|
||||
AddAction("/cameraRemoteView", (id, content) => layoutsCodec.LocalLayoutToggle());
|
||||
|
||||
AddAction("/cameraLayout", (id, content) => layoutsCodec.LocalLayoutToggle());
|
||||
}
|
||||
|
||||
if (Codec is IPasswordPrompt pwCodec)
|
||||
{
|
||||
this.LogVerbose("Adding IPasswordPrompt Actions");
|
||||
|
||||
AddAction("/password", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
|
||||
pwCodec.SubmitPassword(msg.Value);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (Codec is IHasFarEndContentStatus farEndContentStatus)
|
||||
{
|
||||
farEndContentStatus.ReceivingContent.OutputChange +=
|
||||
(sender, args) => PostReceivingContent(args.BoolValue);
|
||||
}
|
||||
|
||||
this.LogVerbose("Adding Privacy & Standby Actions");
|
||||
|
||||
AddAction("/privacyModeOn", (id, content) => Codec.PrivacyModeOn());
|
||||
|
|
@ -393,304 +174,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
}
|
||||
}
|
||||
|
||||
private void PhonebookSyncState_InitialSyncCompleted(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var state = new VideoCodecBaseStateMessage
|
||||
{
|
||||
InitialPhonebookSyncComplete = true
|
||||
};
|
||||
|
||||
PostStatusMessage(state);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting phonebook sync state");
|
||||
}
|
||||
}
|
||||
|
||||
private void CameraIsOffFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||
{
|
||||
PostCameraMode();
|
||||
}
|
||||
|
||||
private void SelfviewIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||
{
|
||||
PostCameraSelfView();
|
||||
}
|
||||
|
||||
private void PresetsCodec_CameraPresetsListHasChanged(object sender, EventArgs e)
|
||||
{
|
||||
PostCameraPresets();
|
||||
}
|
||||
|
||||
private void CameraAutoModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||
{
|
||||
PostCameraMode();
|
||||
}
|
||||
|
||||
|
||||
private void CameraCodec_CameraSelected(object sender, CameraSelectedEventArgs<IHasCameraControls> e)
|
||||
{
|
||||
try
|
||||
{
|
||||
MapCameraActions();
|
||||
PostSelectedCamera();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Exception handling camera selected event");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the camera control actions to the current selected camera on the codec
|
||||
/// </summary>
|
||||
private void MapCameraActions()
|
||||
{
|
||||
if (Codec is IHasCamerasWithControls cameraCodec && cameraCodec.SelectedCamera != null)
|
||||
{
|
||||
RemoveAction("/cameraUp");
|
||||
RemoveAction("/cameraDown");
|
||||
RemoveAction("/cameraLeft");
|
||||
RemoveAction("/cameraRight");
|
||||
RemoveAction("/cameraZoomIn");
|
||||
RemoveAction("/cameraZoomOut");
|
||||
RemoveAction("/cameraHome");
|
||||
|
||||
if (cameraCodec.SelectedCamera is IHasCameraPtzControl camera)
|
||||
{
|
||||
AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, (b) =>
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
camera.TiltUp();
|
||||
return;
|
||||
}
|
||||
|
||||
camera.TiltStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, (b) =>
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
camera.TiltDown();
|
||||
return;
|
||||
}
|
||||
|
||||
camera.TiltStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, (b) =>
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
camera.PanLeft();
|
||||
return;
|
||||
}
|
||||
|
||||
camera.PanStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, (b) =>
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
camera.PanRight();
|
||||
return;
|
||||
}
|
||||
|
||||
camera.PanStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, (b) =>
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
camera.ZoomIn();
|
||||
return;
|
||||
}
|
||||
|
||||
camera.ZoomStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, (b) =>
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
camera.ZoomOut();
|
||||
return;
|
||||
}
|
||||
|
||||
camera.ZoomStop();
|
||||
}));
|
||||
AddAction("/cameraHome", (id, content) => camera.PositionHome());
|
||||
|
||||
|
||||
RemoveAction("/cameraAutoFocus");
|
||||
RemoveAction("/cameraFocusNear");
|
||||
RemoveAction("/cameraFocusFar");
|
||||
|
||||
if (cameraCodec is IHasCameraFocusControl focusCamera)
|
||||
{
|
||||
AddAction("/cameraAutoFocus", (id, content) => focusCamera.TriggerAutoFocus());
|
||||
|
||||
AddAction("/cameraFocusNear", (id, content) => HandleCameraPressAndHold(content, (b) =>
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
focusCamera.FocusNear();
|
||||
return;
|
||||
}
|
||||
|
||||
focusCamera.FocusStop();
|
||||
}));
|
||||
|
||||
AddAction("/cameraFocusFar", (id, content) => HandleCameraPressAndHold(content, (b) =>
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
focusCamera.FocusFar();
|
||||
return;
|
||||
}
|
||||
|
||||
focusCamera.FocusStop();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
|
||||
{
|
||||
var state = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
|
||||
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
|
||||
if (timerHandler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
timerHandler(state.Value, cameraAction);
|
||||
|
||||
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
private string GetCameraMode()
|
||||
{
|
||||
string m = "";
|
||||
|
||||
if (Codec is IHasCameraAutoMode speakerTrackCodec)
|
||||
{
|
||||
m = speakerTrackCodec.CameraAutoModeIsOnFeedback.BoolValue
|
||||
? eCameraControlMode.Auto.ToString().ToLower()
|
||||
: eCameraControlMode.Manual.ToString().ToLower();
|
||||
}
|
||||
|
||||
if (Codec is IHasCameraOff cameraOffCodec)
|
||||
{
|
||||
if (cameraOffCodec.CameraIsOffFeedback.BoolValue)
|
||||
m = eCameraControlMode.Off.ToString().ToLower();
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
private void PostCallHistory()
|
||||
{
|
||||
try
|
||||
{
|
||||
var codec = (Codec as IHasCallHistory);
|
||||
|
||||
if (codec != null)
|
||||
{
|
||||
var status = new VideoCodecBaseStateMessage();
|
||||
|
||||
var recents = codec.CallHistory.RecentCalls;
|
||||
|
||||
if (recents != null)
|
||||
{
|
||||
status.RecentCalls = codec.CallHistory.RecentCalls;
|
||||
|
||||
PostStatusMessage(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting call history");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to grab a call with string ID
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
private CodecActiveCallItem GetCallWithId(string id)
|
||||
{
|
||||
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
private void GetDirectory(string id)
|
||||
{
|
||||
if (!(Codec is IHasDirectory dirCodec))
|
||||
{
|
||||
return;
|
||||
}
|
||||
dirCodec.GetDirectoryFolderContents(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private void GetDirectoryRoot()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(Codec is IHasDirectory dirCodec))
|
||||
{
|
||||
// do something else?
|
||||
return;
|
||||
}
|
||||
if (!dirCodec.PhonebookSyncState.InitialSyncComplete)
|
||||
{
|
||||
var state = new VideoCodecBaseStateMessage
|
||||
{
|
||||
InitialPhonebookSyncComplete = false
|
||||
};
|
||||
|
||||
PostStatusMessage(state);
|
||||
return;
|
||||
}
|
||||
|
||||
dirCodec.SetCurrentDirectoryToRoot();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error getting directory root");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests the parent folder contents
|
||||
/// </summary>
|
||||
private void GetPreviousDirectory()
|
||||
{
|
||||
if (!(Codec is IHasDirectory dirCodec))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dirCodec.GetDirectoryParentFolderContents();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for codec changes
|
||||
/// </summary>
|
||||
|
|
@ -797,96 +280,32 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
Task.Run(() => PostStatusMessage(GetStatus(), id));
|
||||
}
|
||||
|
||||
private void PostReceivingContent(bool receivingContent)
|
||||
{
|
||||
try
|
||||
{
|
||||
var state = new VideoCodecBaseStateMessage
|
||||
{
|
||||
ReceivingContent = receivingContent
|
||||
};
|
||||
|
||||
PostStatusMessage(state);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting receiving content");
|
||||
}
|
||||
}
|
||||
|
||||
private void PostCameraSelfView()
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = new VideoCodecBaseStateMessage
|
||||
{
|
||||
CameraSelfViewIsOn = Codec is IHasCodecSelfView
|
||||
&& (Codec as IHasCodecSelfView).SelfviewIsOnFeedback.BoolValue
|
||||
};
|
||||
|
||||
PostStatusMessage(status);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting camera self view");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Helper to grab a call with string ID
|
||||
/// </summary>
|
||||
private void PostCameraMode()
|
||||
private CodecActiveCallItem GetCallWithId(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = new VideoCodecBaseStateMessage
|
||||
{
|
||||
CameraMode = GetCameraMode()
|
||||
};
|
||||
|
||||
PostStatusMessage(status);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError(ex, "Error posting camera mode");
|
||||
}
|
||||
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
|
||||
}
|
||||
|
||||
private void PostSelectedCamera()
|
||||
private string GetCameraMode()
|
||||
{
|
||||
try
|
||||
{
|
||||
var camerasCodec = Codec as IHasCodecCameras;
|
||||
string m = "";
|
||||
|
||||
var status = new VideoCodecBaseStateMessage
|
||||
{
|
||||
Cameras = new CameraStatus() { SelectedCamera = GetSelectedCamera(camerasCodec) },
|
||||
Presets = GetCurrentPresets()
|
||||
};
|
||||
|
||||
PostStatusMessage(status);
|
||||
}
|
||||
catch (Exception e)
|
||||
if (Codec is IHasCameraAutoMode speakerTrackCodec)
|
||||
{
|
||||
this.LogError(e, "Error posting selected camera");
|
||||
m = speakerTrackCodec.CameraAutoModeIsOnFeedback.BoolValue
|
||||
? eCameraControlMode.Auto.ToString().ToLower()
|
||||
: eCameraControlMode.Manual.ToString().ToLower();
|
||||
}
|
||||
}
|
||||
|
||||
private void PostCameraPresets()
|
||||
{
|
||||
try
|
||||
if (Codec is IHasCameraOff cameraOffCodec)
|
||||
{
|
||||
var status = new VideoCodecBaseStateMessage
|
||||
{
|
||||
Presets = GetCurrentPresets()
|
||||
};
|
||||
if (cameraOffCodec.CameraIsOffFeedback.BoolValue)
|
||||
m = eCameraControlMode.Off.ToString().ToLower();
|
||||
}
|
||||
|
||||
PostStatusMessage(status);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.LogError(e, "Error posting camera presets");
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
private Camera GetSelectedCamera(IHasCodecCameras camerasCodec)
|
||||
|
|
@ -1145,45 +564,4 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
public bool? CanFocus { get; set; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a VideoCodecBaseEventMessage
|
||||
/// </summary>
|
||||
public class VideoCodecBaseEventMessage : DeviceEventMessageBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a PasswordPromptEventMessage
|
||||
/// </summary>
|
||||
public class PasswordPromptEventMessage : VideoCodecBaseEventMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Message
|
||||
/// </summary>
|
||||
[JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Message { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LastAttemptWasIncorrect
|
||||
/// </summary>
|
||||
[JsonProperty("lastAttemptWasIncorrect", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool LastAttemptWasIncorrect { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LoginAttemptFailed
|
||||
/// </summary>
|
||||
[JsonProperty("loginAttemptFailed", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool LoginAttemptFailed { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LoginAttemptCancelled
|
||||
/// </summary>
|
||||
[JsonProperty("loginAttemptCancelled", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool LoginAttemptCancelled { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ using PepperDash.Essentials.Core.Routing;
|
|||
using PepperDash.Essentials.Core.Shades;
|
||||
using PepperDash.Essentials.Devices.Common.AudioCodec;
|
||||
using PepperDash.Essentials.Devices.Common.Cameras;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using PepperDash.Essentials.Devices.Common.Displays;
|
||||
using PepperDash.Essentials.Devices.Common.SoftCodec;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
|
@ -95,7 +96,7 @@ namespace PepperDash.Essentials
|
|||
),
|
||||
new MessengerFactoryEntry(
|
||||
typeof(IHasCamerasWithControls),
|
||||
(d, mp, ck) => new IHasCamerasWithControlMessenger(
|
||||
(d, mp, ck) => new IHasCamerasWithControlsMessenger(
|
||||
$"{d.Key}-cameras-{ck}", mp, (IHasCamerasWithControls)d)
|
||||
),
|
||||
|
||||
|
|
@ -164,6 +165,42 @@ namespace PepperDash.Essentials
|
|||
(d, mp, ck) => new VideoCodecBaseMessenger(
|
||||
$"{d.Key}-videoCodec-{ck}", (VideoCodecBase)d, mp)
|
||||
),
|
||||
new MessengerFactoryEntry(
|
||||
typeof(IHasDirectory),
|
||||
(d, mp, ck) => new IHasDirectoryMessenger(
|
||||
$"{d.Key}-directory-{ck}", mp, d)
|
||||
),
|
||||
new MessengerFactoryEntry(
|
||||
typeof(IHasCallHistory),
|
||||
(d, mp, ck) => new IHasCallHistoryMessenger(
|
||||
$"{d.Key}-callHistory-{ck}", mp, d)
|
||||
),
|
||||
new MessengerFactoryEntry(
|
||||
typeof(IPasswordPrompt),
|
||||
(d, mp, ck) => new IPasswordPromptMessenger(
|
||||
$"{d.Key}-passwordPrompt-{ck}", mp, d)
|
||||
),
|
||||
new MessengerFactoryEntry(
|
||||
typeof(IHasCodecCameras),
|
||||
(d, mp, ck) => new IHasCodecCamerasMessenger(
|
||||
$"{d.Key}-codecCameras-{ck}", mp, (VideoCodecBase)d),
|
||||
predicate: d => d is VideoCodecBase && d is IHasCodecCameras
|
||||
),
|
||||
new MessengerFactoryEntry(
|
||||
typeof(IHasCodecSelfView),
|
||||
(d, mp, ck) => new IHasCodecSelfViewMessenger(
|
||||
$"{d.Key}-selfView-{ck}", mp, d)
|
||||
),
|
||||
new MessengerFactoryEntry(
|
||||
typeof(IHasCodecLayouts),
|
||||
(d, mp, ck) => new IHasCodecLayoutsMessenger(
|
||||
$"{d.Key}-codecLayouts-{ck}", mp, d)
|
||||
),
|
||||
new MessengerFactoryEntry(
|
||||
typeof(IHasFarEndContentStatus),
|
||||
(d, mp, ck) => new IHasFarEndContentStatusMessenger(
|
||||
$"{d.Key}-farEndContent-{ck}", mp, d)
|
||||
),
|
||||
new MessengerFactoryEntry(
|
||||
typeof(IDialerCallStatus),
|
||||
(d, mp, ck) => new IDialerCallStatusMessenger(
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using Crestron.SimplSharp;
|
|||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.Diagnostics;
|
||||
using Crestron.SimplSharpPro.UC;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Abstractions;
|
||||
using PepperDash.Core.Adapters;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue