diff --git a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj
index c074651a..900bfc23 100644
--- a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj
+++ b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj
@@ -26,7 +26,7 @@
-
+
diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs
index ee885abf..ae85b1de 100644
--- a/src/PepperDash.Essentials.Core/Routing/Extensions.cs
+++ b/src/PepperDash.Essentials.Core/Routing/Extensions.cs
@@ -1,4 +1,6 @@
-using Serilog.Events;
+using PepperDash.Essentials.Core.Queues;
+using PepperDash.Essentials.Core.Routing;
+using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -17,6 +19,8 @@ namespace PepperDash.Essentials.Core
{
private static readonly Dictionary RouteRequests = new Dictionary();
+ private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue");
+
///
/// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute
/// and then attempts a new Route and if sucessful, stores that RouteDescriptor
@@ -33,6 +37,15 @@ namespace PepperDash.Essentials.Core
ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort);
}
+ public static void ReleaseRoute(this IRoutingInputs destination)
+ {
+ routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty));
+ }
+
+ public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey)
+ {
+ routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey));
+ }
public static void RemoveRouteRequestForDestination(string destinationKey)
{
@@ -45,133 +58,6 @@ namespace PepperDash.Essentials.Core
Debug.LogMessage(LogEventLevel.Information, messageTemplate, null, destinationKey);
}
- private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null)
- {
- if (destination == null) throw new ArgumentNullException(nameof(destination));
- if (source == null) throw new ArgumentNullException(nameof(source));
- if (destinationPort == null) Debug.LogMessage(LogEventLevel.Information, "Destination port is null");
- if (sourcePort == null) Debug.LogMessage(LogEventLevel.Information, "Source port is null");
-
- var routeRequest = new RouteRequest
- {
- Destination = destination,
- DestinationPort = destinationPort,
- Source = source,
- SourcePort = sourcePort,
- SignalType = signalType
- };
-
-
-
- var coolingDevice = destination as IWarmingCooling;
-
- //We already have a route request for this device, and it's a cooling device and is cooling
- if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
- {
- coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown;
-
- coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
-
- RouteRequests[destination.Key] = routeRequest;
-
- Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down and already has a routing request stored. Storing new route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
-
- return;
- }
-
- //New Request
- if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
- {
- coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
-
- RouteRequests.Add(destination.Key, routeRequest);
-
- Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down. Storing route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
- return;
- }
-
- if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false)
- {
- var handledRequest = RouteRequests[destination.Key];
-
- coolingDevice.IsCoolingDownFeedback.OutputChange -= handledRequest.HandleCooldown;
-
- RouteRequests.Remove(destination.Key);
-
- Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is NOT cooling down. Removing stored route request and routing to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
- }
-
- destination.ReleaseRoute(destinationPort?.Key ?? string.Empty);
-
- RunRouteRequest(routeRequest);
- }
-
- private static void RunRouteRequest(RouteRequest request)
- {
- try
- {
- if (request.Source == null)
- return;
-
- var (audioOrSingleRoute, videoRoute) = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort);
-
- if (audioOrSingleRoute == null && videoRoute == null)
- return;
-
- RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(audioOrSingleRoute);
-
- if (videoRoute != null)
- {
- RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(videoRoute);
- }
-
- Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination);
-
- audioOrSingleRoute.ExecuteRoutes();
- videoRoute?.ExecuteRoutes();
- } catch(Exception ex)
- {
- Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
- }
- }
-
- public static void ReleaseRoute(this IRoutingInputs destination)
- {
- ReleaseRoute(destination, string.Empty);
- }
-
- ///
- /// Will release the existing route on the destination, if it is found in
- /// RouteDescriptorCollection.DefaultCollection
- ///
- ///
- public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey)
- {
- try
- {
- Debug.LogMessage(LogEventLevel.Information, "Release route for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
-
- if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRequest) && destination is IWarmingCooling)
- {
- var coolingDevice = destination as IWarmingCooling;
-
- coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown;
- }
-
- RouteRequests.Remove(destination.Key);
-
- var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination, inputPortKey);
- if (current != null)
- {
- Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
- current.ReleaseRoutes();
- }
- } catch (Exception ex)
- {
- Debug.LogMessage(ex, "Exception releasing route for '{destination}':'{inputPortKey}'",null, destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
- }
- }
-
///
/// Builds a RouteDescriptor that contains the steps necessary to make a route between devices.
/// Routes of type AudioVideo will be built as two separate routes, audio and video. If
@@ -234,6 +120,126 @@ namespace PepperDash.Essentials.Core
return (audioRouteDescriptor, videoRouteDescriptor);
}
+ private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null)
+ {
+ if (destination == null) throw new ArgumentNullException(nameof(destination));
+ if (source == null) throw new ArgumentNullException(nameof(source));
+ if (destinationPort == null) Debug.LogMessage(LogEventLevel.Information, "Destination port is null");
+ if (sourcePort == null) Debug.LogMessage(LogEventLevel.Information, "Source port is null");
+
+ var routeRequest = new RouteRequest
+ {
+ Destination = destination,
+ DestinationPort = destinationPort,
+ Source = source,
+ SourcePort = sourcePort,
+ SignalType = signalType
+ };
+
+ var coolingDevice = destination as IWarmingCooling;
+
+ //We already have a route request for this device, and it's a cooling device and is cooling
+ if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
+ {
+ coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown;
+
+ coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
+
+ RouteRequests[destination.Key] = routeRequest;
+
+ Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down and already has a routing request stored. Storing new route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
+
+ return;
+ }
+
+ //New Request
+ if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
+ {
+ coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
+
+ RouteRequests.Add(destination.Key, routeRequest);
+
+ Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down. Storing route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
+ return;
+ }
+
+ if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false)
+ {
+ var handledRequest = RouteRequests[destination.Key];
+
+ coolingDevice.IsCoolingDownFeedback.OutputChange -= handledRequest.HandleCooldown;
+
+ RouteRequests.Remove(destination.Key);
+
+ Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is NOT cooling down. Removing stored route request and routing to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key);
+ }
+
+ routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty));
+
+ routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest));
+ }
+
+ private static void RunRouteRequest(RouteRequest request)
+ {
+ try
+ {
+ if (request.Source == null)
+ return;
+
+ var (audioOrSingleRoute, videoRoute) = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort);
+
+ if (audioOrSingleRoute == null && videoRoute == null)
+ return;
+
+ RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(audioOrSingleRoute);
+
+ if (videoRoute != null)
+ {
+ RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(videoRoute);
+ }
+
+ Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination);
+
+ audioOrSingleRoute.ExecuteRoutes();
+ videoRoute?.ExecuteRoutes();
+ } catch(Exception ex)
+ {
+ Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
+ }
+ }
+
+ ///
+ /// Will release the existing route on the destination, if it is found in
+ /// RouteDescriptorCollection.DefaultCollection
+ ///
+ ///
+ private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey)
+ {
+ try
+ {
+ Debug.LogMessage(LogEventLevel.Information, "Release route for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
+
+ if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRequest) && destination is IWarmingCooling)
+ {
+ var coolingDevice = destination as IWarmingCooling;
+
+ coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown;
+ }
+
+ RouteRequests.Remove(destination.Key);
+
+ var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination, inputPortKey);
+ if (current != null)
+ {
+ Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
+ current.ReleaseRoutes();
+ }
+ } catch (Exception ex)
+ {
+ Debug.LogMessage(ex, "Exception releasing route for '{destination}':'{inputPortKey}'",null, destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
+ }
+ }
+
///
/// The recursive part of this. Will stop on each device, search its inputs for the
/// desired source and if not found, invoke this function for the each input port
diff --git a/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs b/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs
index bd8a42d2..19d8655b 100644
--- a/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs
+++ b/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs
@@ -38,5 +38,10 @@ namespace PepperDash.Essentials.Core
Debug.LogMessage(ex, "Exception handling cooldown", Destination);
}
}
+
+ public override string ToString()
+ {
+ return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}";
+ }
}
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs b/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs
new file mode 100644
index 00000000..05681991
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs
@@ -0,0 +1,45 @@
+using PepperDash.Core;
+using PepperDash.Essentials.Core.Queues;
+using System;
+using Serilog.Events;
+
+namespace PepperDash.Essentials.Core.Routing
+{
+ public class RouteRequestQueueItem : IQueueMessage
+ {
+ private readonly Action action;
+ private readonly RouteRequest routeRequest;
+
+ public RouteRequestQueueItem(Action routeAction, RouteRequest request)
+ {
+ action = routeAction;
+ routeRequest = request;
+ }
+
+ public void Dispatch()
+ {
+ Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest);
+ action(routeRequest);
+ }
+ }
+
+ public class ReleaseRouteQueueItem : IQueueMessage
+ {
+ private readonly Action action;
+ private readonly IRoutingInputs destination;
+ private readonly string inputPortKey;
+
+ public ReleaseRouteQueueItem(Action action, IRoutingInputs destination, string inputPortKey)
+ {
+ this.action = action;
+ this.destination = destination;
+ this.inputPortKey = inputPortKey;
+ }
+
+ public void Dispatch()
+ {
+ Debug.LogMessage(LogEventLevel.Information, "Dispatching release route request for {destination}:{inputPortKey}", null, destination?.Key ?? "no destination", string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
+ action(destination, inputPortKey);
+ }
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj
index 69f6d24e..d87662fb 100644
--- a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj
+++ b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj
@@ -30,6 +30,6 @@
-
+
\ 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 f623c539..7fdad9b4 100644
--- a/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs
+++ b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs
@@ -28,14 +28,14 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
for(var i = 1; i <= props.OutputCount; i++)
{
- var outputPort = new RoutingOutputPort($"{Key}-output{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this);
+ var outputPort = new RoutingOutputPort($"output{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this);
OutputPorts.Add(outputPort);
}
for(var i = 1; i<= props.ContentInputCount; i++)
{
- var inputPort = new RoutingInputPort($"{Key}-contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this);
+ var inputPort = new RoutingInputPort($"contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this);
InputPorts.Add(inputPort);
}
@@ -47,7 +47,7 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
for(var i = 1; i <=props.CameraInputCount; i++)
{
- var cameraPort = new RoutingInputPort($"{Key}-cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this);
+ var cameraPort = new RoutingInputPort($"cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this);
InputPorts.Add(cameraPort);
}
diff --git a/src/PepperDash.Essentials/PepperDash.Essentials.csproj b/src/PepperDash.Essentials/PepperDash.Essentials.csproj
index d64846e5..68cdf106 100644
--- a/src/PepperDash.Essentials/PepperDash.Essentials.csproj
+++ b/src/PepperDash.Essentials/PepperDash.Essentials.csproj
@@ -49,7 +49,7 @@
-
+