feat: Refactor routing interfaces and feedback mechanisms

- Removed ITxRouting and ITxRoutingWithFeedback interfaces as they were redundant.
- Updated RouteDescriptor and RouteSwitchDescriptor to use new feedback interfaces.
- Modified RoutingFeedbackManager to utilize IRoutingSinkWithFeedback and IRoutingMidpointWithFeedback.
- Adjusted GenericAudioOut, BlueJeansPc, and other device classes to implement new feedback interfaces.
- Introduced new messenger classes for IRoutingSinkWithFeedback and IRoutingMidpointWithFeedback.
- Cleaned up unused messenger interfaces and consolidated routing logic.
- Updated MobileControlEssentialsRoomBridge to remove dependency on IHasCurrentSourceInfoChange.
This commit is contained in:
Neil Dorin 2026-05-14 14:36:30 -06:00
parent b9dcec587d
commit f64b595fd7
46 changed files with 324 additions and 872 deletions

View file

@ -12,11 +12,16 @@ namespace PepperDash.Essentials.Devices.Common;
/// <summary>
/// Represents and audio endpoint
/// </summary>
public class GenericAudioOut : EssentialsDevice, IRoutingSink
public class GenericAudioOut : EssentialsDevice, IRoutingSinkWithFeedback
{
/// <inheritdoc/>
public RoutingInputPort CurrentInputPort => AnyAudioIn;
/// <inheritdoc/>
public event InputChangedEventHandler InputChanged;
/// <inheritdoc/>
public void ExecuteSwitch(object inputSelector) { }
/// <inheritdoc/>
public Dictionary<eRoutingSignalType, IRoutingSource> CurrentSources { get; private set; }

View file

@ -229,7 +229,7 @@ public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced
t.Start();
}
#region IRoutingSink Members
#region IRoutingSinkWithFeedback Members
/// <summary>
/// Typically called by the discovery routing algorithm.

View file

@ -15,7 +15,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays;
/// <summary>
/// Represents a mock display device for testing and simulation purposes.
/// </summary>
public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs<string>, IRoutingSinkWithSwitchingWithInputPort, IHasPowerControlWithFeedback
public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs<string>, IHasPowerControlWithFeedback
{
/// <inheritdoc />
public ISelectableItems<string> Inputs { get; private set; }

View file

@ -7,7 +7,7 @@ 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.
/// </summary>
public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback
public abstract class TwoWayDisplayBase : DisplayBase, IHasPowerControlWithFeedback
{
/// <summary>
/// Gets feedback for the current input selection on the display.

View file

@ -12,7 +12,7 @@ namespace PepperDash.Essentials.Devices.Common.Generic;
/// <summary>
/// Represents a GenericSink
/// </summary>
public class GenericSink : EssentialsDevice, IRoutingSinkWithSwitchingWithInputPort, ICurrentSources
public class GenericSink : EssentialsDevice, IRoutingSinkWithFeedback
{
/// <inheritdoc/>
public Dictionary<eRoutingSignalType, IRoutingSource> CurrentSources { get; private set; }
@ -104,43 +104,13 @@ public class GenericSink : EssentialsDevice, IRoutingSinkWithSwitchingWithInputP
/// </summary>
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
/// <summary>
/// Gets or sets the CurrentSourceInfoKey
/// </summary>
public string CurrentSourceInfoKey { get; set; }
private SourceListItem _currentSource;
/// <summary>
/// Gets or sets the CurrentSourceInfo
/// </summary>
public SourceListItem CurrentSourceInfo
{
get => _currentSource;
set
{
if (value == _currentSource)
{
return;
}
CurrentSourceChange?.Invoke(_currentSource, ChangeType.WillChange);
_currentSource = value;
CurrentSourceChange?.Invoke(_currentSource, ChangeType.DidChange);
}
}
/// <summary>
/// Gets the current input port
/// </summary>
public RoutingInputPort CurrentInputPort => InputPorts[0];
/// <summary>
/// Event fired when the current source changes
/// </summary>
public event SourceInfoChangeHandler CurrentSourceChange;
/// <inheritdoc />
public event InputChangedEventHandler InputChanged;

View file

@ -15,7 +15,7 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec;
/// <summary>
/// Class representing a BlueJeans soft codec running on an in-room PC.
/// </summary>
public class BlueJeansPc : InRoomPc, IRunRouteAction, IRoutingSink
public class BlueJeansPc : InRoomPc, IRunRouteAction, IRoutingSinkWithFeedback
{
/// <summary>
@ -29,6 +29,12 @@ public class BlueJeansPc : InRoomPc, IRunRouteAction, IRoutingSink
/// </summary>
public RoutingInputPort CurrentInputPort => AnyVideoIn;
/// <inheritdoc/>
public event InputChangedEventHandler InputChanged;
/// <inheritdoc/>
public void ExecuteSwitch(object inputSelector) { }
/// <inheritdoc/>
public Dictionary<eRoutingSignalType, IRoutingSource> CurrentSources { get; private set; }
@ -170,16 +176,7 @@ public class BlueJeansPc : InRoomPc, IRunRouteAction, IRoutingSink
}
// store the name and UI info for routes
if (item.SourceKey == "none")
{
CurrentSourceInfoKey = routeKey;
CurrentSourceInfo = null;
}
else if (item.SourceKey != null)
{
CurrentSourceInfoKey = routeKey;
CurrentSourceInfo = item;
}
// CurrentSourceInfo tracking removed in v3 interface consolidation
// report back when done
if (successCallback != null)
@ -196,9 +193,9 @@ public class BlueJeansPc : InRoomPc, IRunRouteAction, IRoutingSink
/// <returns></returns>
bool DoRoute(SourceRouteListItem route)
{
IRoutingSink dest = null;
IRoutingSinkWithFeedback dest = null;
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkWithFeedback;
if (dest == null)
{
@ -227,42 +224,5 @@ public class BlueJeansPc : InRoomPc, IRunRouteAction, IRoutingSink
#region IHasCurrentSourceInfoChange Members
/// <inheritdoc />
public string CurrentSourceInfoKey { get; set; }
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _CurrentSourceInfo; }
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
// remove from in-use tracker, if so equipped
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
// add to in-use tracking
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
/// <inheritdoc />
public event SourceInfoChangeHandler CurrentSourceChange;
#endregion
}

View file

@ -12,7 +12,7 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec;
/// <summary>
/// Represents a GenericSoftCodec
/// </summary>
public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSinkWithSwitchingWithInputPort
public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSinkWithFeedback
{
private RoutingInputPort _currentInputPort;
@ -141,46 +141,11 @@ public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSinkWi
/// </summary>
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
/// <summary>
/// <summary>
/// Gets or sets the OutputPorts
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
/// <summary>
/// Gets or sets the CurrentSourceInfoKey
/// </summary>
public string CurrentSourceInfoKey { get; set; }
/// <summary>
/// Gets or sets the CurrentSourceInfo
/// </summary>
public SourceListItem CurrentSourceInfo
{
get
{
return _CurrentSourceInfo;
}
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
/// <summary>
/// Event fired when the current source changes
/// </summary>
public event SourceInfoChangeHandler CurrentSourceChange;
/// <summary>
/// Event fired when the input changes

View file

@ -27,7 +27,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec;
/// Base class for video codecs. Contains common properties, methods, and feedback for video codecs.
/// Also contains the logic to link commonly implemented interfaces to the API bridge.
/// </summary>
public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs,
public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingMidpoint,
IUsageTracking, ICodecCallControls, IHasContentSharing, ICodecAudio, IVideoCodecInfo, IBridgeAdvanced, IHasStandbyMode, IHasReady
{
private const int XSigEncoding = 28591;
@ -302,7 +302,7 @@ public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutpu
#endregion
#region IRoutingInputsOutputs Members
#region IRoutingMidpoint Members
/// <summary>
/// Gets or sets the InputPorts