mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-01-11 19:44:52 +00:00
Merge pull request #462 from PepperDash/release/1.6.5
Release/1.6.5 Development
This commit is contained in:
@@ -11,5 +11,8 @@ namespace PepperDash_Essentials_Core.DeviceTypeInterfaces
|
||||
List<LanguageLabel> UiLabels { get; set; }
|
||||
List<LanguageLabel> Sources { get; set; }
|
||||
List<LanguageLabel> Destinations { get; set; }
|
||||
List<LanguageLabel> SourceGroupNames { get; set; }
|
||||
List<LanguageLabel> DestinationGroupNames { get; set; }
|
||||
List<LanguageLabel> RoomNames { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public interface IHasDspPresets
|
||||
{
|
||||
List<IDspPreset> Presets { get; }
|
||||
|
||||
void RecallPreset(IDspPreset preset);
|
||||
|
||||
}
|
||||
|
||||
public interface IDspPreset
|
||||
{
|
||||
string Name { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash_Essentials_Core.Gateways
|
||||
{
|
||||
public class CenCn2Controller
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -190,6 +190,7 @@
|
||||
<Compile Include="Devices\EssentialsBridgeableDevice.cs" />
|
||||
<Compile Include="Devices\EssentialsDevice.cs" />
|
||||
<Compile Include="Devices\GenericIRController.cs" />
|
||||
<Compile Include="Devices\IDspPreset.cs" />
|
||||
<Compile Include="Devices\IProjectorInterfaces.cs" />
|
||||
<Compile Include="Devices\PC\InRoomPc.cs" />
|
||||
<Compile Include="Devices\PC\Laptop.cs" />
|
||||
|
||||
@@ -118,7 +118,10 @@ namespace PepperDash.Essentials.DM
|
||||
OutputEndpointOnlineFeedbacks = new Dictionary<uint, BoolFeedback>();
|
||||
|
||||
Debug.Console(1, this, "{0} Switcher Inputs Present.", Dmps.SwitcherInputs.Count);
|
||||
Debug.Console(1, this, "{0} Switcher Outputs Present.", Dmps.SwitcherOutputs.Count);
|
||||
Debug.Console(1, this, "{0} Switcher Outputs Present.", Dmps.SwitcherOutputs.Count);
|
||||
|
||||
Debug.Console(1, this, "{0} Inputs in ControlSystem", Dmps.NumberOfSwitcherInputs);
|
||||
Debug.Console(1, this, "{0} Outputs in ControlSystem", Dmps.NumberOfSwitcherOutputs);
|
||||
|
||||
SetupOutputCards();
|
||||
|
||||
@@ -128,32 +131,50 @@ namespace PepperDash.Essentials.DM
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
// Set input and output names from config
|
||||
if (InputNames != null)
|
||||
{
|
||||
foreach (var kvp in InputNames)
|
||||
{
|
||||
var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput);
|
||||
if (input != null)
|
||||
input.Name.StringValue = kvp.Value;
|
||||
}
|
||||
}
|
||||
if (OutputNames != null)
|
||||
{
|
||||
foreach (var kvp in OutputNames)
|
||||
{
|
||||
var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput);
|
||||
if (output != null)
|
||||
output.Name.StringValue = kvp.Value;
|
||||
}
|
||||
}
|
||||
SetInputNames();
|
||||
|
||||
SetOutputNames();
|
||||
|
||||
// Subscribe to events
|
||||
Dmps.DMInputChange += new DMInputEventHandler(Dmps_DMInputChange);
|
||||
Dmps.DMOutputChange += new DMOutputEventHandler(Dmps_DMOutputChange);
|
||||
Dmps.DMInputChange += Dmps_DMInputChange;
|
||||
Dmps.DMOutputChange += Dmps_DMOutputChange;
|
||||
|
||||
return base.CustomActivate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SetOutputNames()
|
||||
{
|
||||
if (OutputNames == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var kvp in OutputNames)
|
||||
{
|
||||
var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput);
|
||||
if (output != null && output.Name.Type != eSigType.NA)
|
||||
{
|
||||
output.Name.StringValue = kvp.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetInputNames()
|
||||
{
|
||||
if (InputNames == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var kvp in InputNames)
|
||||
{
|
||||
var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput);
|
||||
if (input != null && input.Name.Type != eSigType.NA)
|
||||
{
|
||||
input.Name.StringValue = kvp.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
|
||||
{
|
||||
var joinMap = new DmpsRoutingControllerJoinMap(joinStart);
|
||||
@@ -175,171 +196,197 @@ namespace PepperDash.Essentials.DM
|
||||
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||
|
||||
// Link up outputs
|
||||
for (uint i = 1; i <= Dmps.NumberOfSwitcherInputs; i++)
|
||||
{
|
||||
Debug.Console(2, this, "Linking Input Card {0}", i);
|
||||
LinkInputsToApi(trilist, joinMap);
|
||||
|
||||
var ioSlot = i;
|
||||
var ioSlotJoin = ioSlot - 1;
|
||||
|
||||
//if (TxDictionary.ContainsKey(ioSlot))
|
||||
//{
|
||||
// Debug.Console(2, "Creating Tx Feedbacks {0}", ioSlot);
|
||||
// var TxKey = TxDictionary[ioSlot];
|
||||
// var TxDevice = DeviceManager.GetDeviceForKey(TxKey) as DmTxControllerBase;
|
||||
// //TxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
|
||||
// // TxDevice.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
|
||||
// // trilist.SetUShortSigAction((ApiMap.HdcpSupport[ioSlot]), u => TxDevice.SetHdcpSupportAll((ePdtHdcpSupport)(u)));
|
||||
// // TxDevice.HdcpSupportAllFeedback.LinkInputSig(trilist.UShortInput[joinMap. + ioSlot]);
|
||||
// // trilist.UShortInput[ApiMap.HdcpSupportCapability[ioSlot]].UShortValue = TxDevice.HdcpSupportCapability;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// // dmChassis.VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[ApiMap.TxVideoSyncStatus[ioSlot]]);
|
||||
//}
|
||||
|
||||
if (VideoInputSyncFeedbacks[ioSlot] != null)
|
||||
VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]);
|
||||
|
||||
if (InputNameFeedbacks[ioSlot] != null)
|
||||
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]);
|
||||
LinkOutputsToApi(trilist, joinMap);
|
||||
}
|
||||
|
||||
private void LinkOutputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
|
||||
{
|
||||
for (uint i = 1; i <= Dmps.SwitcherOutputs.Count; i++)
|
||||
{
|
||||
Debug.Console(2, this, "Linking Output Card {0}", i);
|
||||
|
||||
trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, new Action<string>(s =>
|
||||
{
|
||||
var inputCard = Dmps.SwitcherInputs[ioSlot] as DMInput;
|
||||
|
||||
if (inputCard != null)
|
||||
{
|
||||
if (inputCard.NameFeedback != null && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue) && inputCard.NameFeedback.StringValue != s)
|
||||
if (inputCard.Name != null)
|
||||
inputCard.Name.StringValue = s;
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
if (InputEndpointOnlineFeedbacks[ioSlot] != null)
|
||||
InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
|
||||
for (uint i = 1; i <= Dmps.NumberOfSwitcherOutputs; i++)
|
||||
{
|
||||
Debug.Console(2, this, "Linking Output Card {0}", i);
|
||||
|
||||
var ioSlot = i;
|
||||
var ioSlotJoin = ioSlot - 1;
|
||||
|
||||
var ioSlotJoin = ioSlot - 1;
|
||||
|
||||
// Control
|
||||
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video));
|
||||
trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin, o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio));
|
||||
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin,
|
||||
o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video));
|
||||
trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin,
|
||||
o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio));
|
||||
|
||||
trilist.SetStringSigAction(joinMap.OutputNames.JoinNumber + ioSlotJoin, s =>
|
||||
{
|
||||
var outputCard = Dmps.SwitcherOutputs[ioSlot] as DMOutput;
|
||||
|
||||
//Debug.Console(2, dmpsRouter, "Output Name String Sig Action for Output Card {0}", ioSlot);
|
||||
|
||||
if (outputCard != null)
|
||||
{
|
||||
//Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType);
|
||||
|
||||
if (!(outputCard is Card.Dmps3CodecOutput) && outputCard.NameFeedback != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
|
||||
{
|
||||
//Debug.Console(2, dmpsRouter, "NameFeedabck: {0}", outputCard.NameFeedback.StringValue);
|
||||
|
||||
if (outputCard.NameFeedback.StringValue != s && outputCard.Name != null)
|
||||
{
|
||||
outputCard.Name.StringValue = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Feedback
|
||||
trilist.SetStringSigAction(joinMap.OutputNames.JoinNumber + ioSlotJoin, s =>
|
||||
{
|
||||
var outputCard = Dmps.SwitcherOutputs[ioSlot] as DMOutput;
|
||||
|
||||
//Debug.Console(2, dmpsRouter, "Output Name String Sig Action for Output Card {0}", ioSlot);
|
||||
|
||||
if (outputCard == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType);
|
||||
|
||||
if (outputCard is Card.Dmps3CodecOutput || outputCard.NameFeedback == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Debug.Console(2, dmpsRouter, "NameFeedabck: {0}", outputCard.NameFeedback.StringValue);
|
||||
|
||||
if (outputCard.NameFeedback.StringValue != s && outputCard.Name != null)
|
||||
{
|
||||
outputCard.Name.StringValue = s;
|
||||
}
|
||||
});
|
||||
|
||||
// Feedback
|
||||
if (VideoOutputFeedbacks[ioSlot] != null)
|
||||
VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]);
|
||||
{
|
||||
VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
if (AudioOutputFeedbacks[ioSlot] != null)
|
||||
AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]);
|
||||
{
|
||||
AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
if (OutputNameFeedbacks[ioSlot] != null)
|
||||
OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]);
|
||||
{
|
||||
OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
if (OutputVideoRouteNameFeedbacks[ioSlot] != null)
|
||||
OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]);
|
||||
{
|
||||
OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(
|
||||
trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
if (OutputAudioRouteNameFeedbacks[ioSlot] != null)
|
||||
OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]);
|
||||
{
|
||||
OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig(
|
||||
trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
if (OutputEndpointOnlineFeedbacks[ioSlot] != null)
|
||||
OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
|
||||
trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
|
||||
{
|
||||
for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++)
|
||||
{
|
||||
Debug.Console(2, this, "Linking Input Card {0}", i);
|
||||
|
||||
var ioSlot = i;
|
||||
var ioSlotJoin = ioSlot - 1;
|
||||
|
||||
if (VideoInputSyncFeedbacks[ioSlot] != null)
|
||||
{
|
||||
VideoInputSyncFeedbacks[ioSlot].LinkInputSig(
|
||||
trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
|
||||
if (InputNameFeedbacks[ioSlot] != null)
|
||||
{
|
||||
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
|
||||
trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s =>
|
||||
{
|
||||
var inputCard = Dmps.SwitcherInputs[ioSlot] as DMInput;
|
||||
|
||||
if (inputCard == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputCard.NameFeedback == null || string.IsNullOrEmpty(inputCard.NameFeedback.StringValue) ||
|
||||
inputCard.NameFeedback.StringValue == s)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputCard.Name != null)
|
||||
{
|
||||
inputCard.Name.StringValue = s;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (InputEndpointOnlineFeedbacks[ioSlot] != null)
|
||||
{
|
||||
InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
|
||||
trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Iterate the SwitcherOutputs collection to setup feedbacks and add routing ports
|
||||
/// </summary>
|
||||
void SetupOutputCards()
|
||||
{
|
||||
foreach (var card in Dmps.SwitcherOutputs)
|
||||
{
|
||||
|
||||
var outputCard = card as DMOutput;
|
||||
foreach (var card in Dmps.SwitcherOutputs)
|
||||
{
|
||||
Debug.Console(1, this, "Output Card Type: {0}", card.CardInputOutputType);
|
||||
|
||||
var outputCard = card as DMOutput;
|
||||
|
||||
if (outputCard == null)
|
||||
{
|
||||
Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType);
|
||||
continue;
|
||||
}
|
||||
|
||||
Debug.Console(1, this, "Adding Output Card Number {0} Type: {1}", outputCard.Number, outputCard.CardInputOutputType.ToString());
|
||||
|
||||
if (outputCard != null)
|
||||
VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
|
||||
{
|
||||
VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
|
||||
{
|
||||
if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; }
|
||||
else { return 0; };
|
||||
});
|
||||
AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
|
||||
{
|
||||
if (outputCard.AudioOutFeedback != null) { return (ushort)outputCard.AudioOutFeedback.Number; }
|
||||
else { return 0; };
|
||||
});
|
||||
if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; }
|
||||
return 0;
|
||||
;
|
||||
});
|
||||
AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
|
||||
{
|
||||
if (outputCard.AudioOutFeedback != null) { return (ushort)outputCard.AudioOutFeedback.Number; }
|
||||
return 0;
|
||||
;
|
||||
});
|
||||
|
||||
OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
|
||||
OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
|
||||
{
|
||||
if (outputCard.NameFeedback != null && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
|
||||
{
|
||||
if (outputCard.NameFeedback != null && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
|
||||
{
|
||||
Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue);
|
||||
return outputCard.NameFeedback.StringValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
});
|
||||
Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue);
|
||||
return outputCard.NameFeedback.StringValue;
|
||||
}
|
||||
return "";
|
||||
});
|
||||
|
||||
OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
|
||||
OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
|
||||
{
|
||||
if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null)
|
||||
{
|
||||
if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null)
|
||||
{
|
||||
return outputCard.VideoOutFeedback.NameFeedback.StringValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NoRouteText;
|
||||
}
|
||||
});
|
||||
OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
|
||||
return outputCard.VideoOutFeedback.NameFeedback.StringValue;
|
||||
}
|
||||
return NoRouteText;
|
||||
});
|
||||
OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
|
||||
{
|
||||
if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null)
|
||||
{
|
||||
if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null)
|
||||
{
|
||||
return outputCard.AudioOutFeedback.NameFeedback.StringValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NoRouteText;
|
||||
return outputCard.AudioOutFeedback.NameFeedback.StringValue;
|
||||
}
|
||||
return NoRouteText;
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => outputCard.EndpointOnlineFeedback);
|
||||
|
||||
OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => { return outputCard.EndpointOnlineFeedback; });
|
||||
|
||||
AddOutputCard(outputCard.Number, outputCard);
|
||||
}
|
||||
AddOutputCard(outputCard.Number, outputCard);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,18 +541,23 @@ namespace PepperDash.Essentials.DM
|
||||
|
||||
var cecPort = hdmiOutputCard.HdmiOutputPort;
|
||||
|
||||
AddHdmiOutputPort(number, cecPort);
|
||||
|
||||
return;
|
||||
AddHdmiOutputPort(number, cecPort);
|
||||
}
|
||||
else if (outputCard is Card.Dmps3HdmiOutputBackend)
|
||||
{
|
||||
var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend;
|
||||
|
||||
var cecPort = hdmiOutputCard.HdmiOutputPort;
|
||||
|
||||
AddHdmiOutputPort(number, cecPort);
|
||||
}
|
||||
else if (outputCard is Card.Dmps3DmOutput)
|
||||
{
|
||||
var dmOutputCard = outputCard as Card.Dmps3DmOutput;
|
||||
|
||||
var cecPort = dmOutputCard.DmOutputPort;
|
||||
|
||||
AddDmOutputPort(number);
|
||||
return;
|
||||
{
|
||||
AddDmOutputPort(number);
|
||||
}
|
||||
else if (outputCard is Card.Dmps3DmOutputBackend)
|
||||
{
|
||||
AddDmOutputPort(number);
|
||||
}
|
||||
else if (outputCard is Card.Dmps3ProgramOutput)
|
||||
{
|
||||
@@ -513,50 +565,51 @@ namespace PepperDash.Essentials.DM
|
||||
|
||||
var programOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
|
||||
|
||||
DeviceManager.AddDevice(programOutput);
|
||||
|
||||
return;
|
||||
DeviceManager.AddDevice(programOutput);
|
||||
}
|
||||
else if (outputCard is Card.Dmps3AuxOutput)
|
||||
{
|
||||
if (outputCard.CardInputOutputType == eCardInputOutputType.Dmps3Aux1Output)
|
||||
{
|
||||
AddAudioOnlyOutputPort(number, "Aux1");
|
||||
else if (outputCard is Card.Dmps3AuxOutput)
|
||||
{
|
||||
switch (outputCard.CardInputOutputType)
|
||||
{
|
||||
case eCardInputOutputType.Dmps3Aux1Output:
|
||||
{
|
||||
AddAudioOnlyOutputPort(number, "Aux1");
|
||||
|
||||
var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
|
||||
var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
|
||||
|
||||
DeviceManager.AddDevice(aux1Output);
|
||||
}
|
||||
else if (outputCard.CardInputOutputType == eCardInputOutputType.Dmps3Aux2Output)
|
||||
{
|
||||
AddAudioOnlyOutputPort(number, "Aux2");
|
||||
DeviceManager.AddDevice(aux1Output);
|
||||
}
|
||||
break;
|
||||
case eCardInputOutputType.Dmps3Aux2Output:
|
||||
{
|
||||
AddAudioOnlyOutputPort(number, "Aux2");
|
||||
|
||||
var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
|
||||
var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
|
||||
|
||||
DeviceManager.AddDevice(aux2Output);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (outputCard is Card.Dmps3CodecOutput)
|
||||
{
|
||||
if (number == (uint)CrestronControlSystem.eDmps300cOutputs.Codec1
|
||||
|| number == (uint)CrestronControlSystem.eDmps3200cOutputs.Codec1
|
||||
|| number == (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec1
|
||||
|| number == (uint)CrestronControlSystem.eDmps34K250COutputs.Codec1
|
||||
|| number == (uint)CrestronControlSystem.eDmps34K350COutputs.Codec1)
|
||||
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec1.ToString());
|
||||
else if (number == (uint)CrestronControlSystem.eDmps300cOutputs.Codec2
|
||||
|| number == (uint)CrestronControlSystem.eDmps3200cOutputs.Codec2
|
||||
|| number == (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec2
|
||||
|| number == (uint)CrestronControlSystem.eDmps34K250COutputs.Codec2
|
||||
|| number == (uint)CrestronControlSystem.eDmps34K350COutputs.Codec2)
|
||||
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec2.ToString());
|
||||
return;
|
||||
}
|
||||
DeviceManager.AddDevice(aux2Output);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (outputCard is Card.Dmps3CodecOutput)
|
||||
{
|
||||
switch (number)
|
||||
{
|
||||
case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec1:
|
||||
case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec1:
|
||||
case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec1:
|
||||
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec1.ToString());
|
||||
break;
|
||||
case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec2:
|
||||
case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec2:
|
||||
case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec2:
|
||||
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec2.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (outputCard is Card.Dmps3DialerOutput)
|
||||
{
|
||||
AddAudioOnlyOutputPort(number, "Dialer");
|
||||
return;
|
||||
AddAudioOnlyOutputPort(number, "Dialer");
|
||||
}
|
||||
else if (outputCard is Card.Dmps3DigitalMixOutput)
|
||||
{
|
||||
@@ -567,13 +620,11 @@ namespace PepperDash.Essentials.DM
|
||||
if (number == (uint)CrestronControlSystem.eDmps34K250COutputs.Mix2
|
||||
|| number == (uint)CrestronControlSystem.eDmps34K300COutputs.Mix2
|
||||
|| number == (uint)CrestronControlSystem.eDmps34K350COutputs.Mix2)
|
||||
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString());
|
||||
return;
|
||||
AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString());
|
||||
}
|
||||
else if (outputCard is Card.Dmps3AecOutput)
|
||||
{
|
||||
AddAudioOnlyOutputPort(number, "Aec");
|
||||
return;
|
||||
AddAudioOnlyOutputPort(number, "Aec");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Crestron.SimplSharpPro.DM;
|
||||
using Crestron.SimplSharpPro.DM.Cards;
|
||||
using Crestron.SimplSharpPro.DM.Endpoints.Receivers;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
@@ -221,6 +222,10 @@ namespace PepperDash.Essentials.DM
|
||||
DmRmcPropertiesConfig props, string pKey, uint ipid)
|
||||
{
|
||||
var parentDev = DeviceManager.GetDeviceForKey(pKey);
|
||||
if (parentDev is DmpsRoutingController)
|
||||
{
|
||||
return GetDmRmcControllerForDmps(key, name, typeName, parentDev as DmpsRoutingController, props.ParentOutputNumber);
|
||||
}
|
||||
if (!(parentDev is IDmSwitch))
|
||||
{
|
||||
Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a DM Chassis.",
|
||||
@@ -285,6 +290,28 @@ namespace PepperDash.Essentials.DM
|
||||
return null;
|
||||
}
|
||||
|
||||
private static CrestronGenericBaseDevice GetDmRmcControllerForDmps(string key, string name, string typeName,
|
||||
DmpsRoutingController controller, uint num)
|
||||
{
|
||||
Func<string, string, DMOutput, CrestronGenericBaseDevice> dmpsHandler;
|
||||
if (ChassisCpu3Dict.TryGetValue(typeName.ToLower(), out dmpsHandler))
|
||||
{
|
||||
var output = controller.Dmps.SwitcherOutputs[num] as DMOutput;
|
||||
|
||||
if (output != null)
|
||||
{
|
||||
return dmpsHandler(key, name, output);
|
||||
}
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error,
|
||||
"Cannot attach DM-RMC of type '{0}' to output {1} on DMPS chassis. Output is not a DM Output.",
|
||||
typeName, num);
|
||||
return null;
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error, "Cannot create DM-RMC of type '{0}' to output {1} on DMPS chassis", typeName, num);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static CrestronGenericBaseDevice GetDmRmcControllerForProcessor(string key, string name, string typeName, uint ipid)
|
||||
{
|
||||
try
|
||||
@@ -305,6 +332,8 @@ namespace PepperDash.Essentials.DM
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class DmRmcControllerFactory : EssentialsDeviceFactory<DmRmcControllerBase>
|
||||
|
||||
@@ -6,390 +6,398 @@ using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
|
||||
// QUESTIONS:
|
||||
//
|
||||
// When subscribing, just use the Instance ID for Custom Name?
|
||||
|
||||
// Verbose on subscriptions?
|
||||
|
||||
// Example subscription feedback responses
|
||||
// ! "publishToken":"name" "value":-77.0
|
||||
// ! "myLevelName" -77
|
||||
|
||||
public class BiampTesiraForteDsp : DspBase
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
new public Dictionary<string, TesiraForteLevelControl> LevelControlPoints { get; private set; }
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
private CTimer SubscriptionTimer;
|
||||
|
||||
CrestronQueue CommandQueue;
|
||||
|
||||
bool CommandQueueInProgress = false;
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shows received lines as hex
|
||||
/// </summary>
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public BiampTesiraForteDsp(string key, string name, IBasicCommunication comm, BiampTesiraFortePropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
CommandQueue = new CrestronQueue(100);
|
||||
|
||||
Communication = comm;
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// This instance uses IP control
|
||||
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This instance uses RS-232 control
|
||||
}
|
||||
PortGather = new CommunicationGather(Communication, "\x0d\x0a");
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
//#warning Need to deal with this poll string
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000, "SESSION get aliases\x0d\x0a");
|
||||
}
|
||||
|
||||
LevelControlPoints = new Dictionary<string, TesiraForteLevelControl>();
|
||||
|
||||
foreach (KeyValuePair<string, BiampTesiraForteLevelControlBlockConfig> block in props.LevelControlBlocks)
|
||||
{
|
||||
this.LevelControlPoints.Add(block.Key, new TesiraForteLevelControl(block.Key, block.Value, this));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
// Tasks on connect
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cleanup items from this session
|
||||
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer.Stop();
|
||||
SubscriptionTimer = null;
|
||||
}
|
||||
|
||||
isSubscribed = false;
|
||||
CommandQueue.Clear();
|
||||
CommandQueueInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the subscription process to the DSP
|
||||
/// </summary>
|
||||
void SubscribeToAttributes()
|
||||
{
|
||||
SendLine("SESSION set verbose true");
|
||||
|
||||
foreach (KeyValuePair<string, TesiraForteLevelControl> level in LevelControlPoints)
|
||||
{
|
||||
level.Value.Subscribe();
|
||||
}
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
|
||||
ResetSubscriptionTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets or Sets the subscription timer
|
||||
/// </summary>
|
||||
void ResetSubscriptionTimer()
|
||||
{
|
||||
isSubscribed = true;
|
||||
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer = new CTimer(o => SubscribeToAttributes(), 30000);
|
||||
SubscriptionTimer.Reset();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a response message from the DSP
|
||||
/// </summary>
|
||||
/// <param name="dev"></param>
|
||||
/// <param name="args"></param>
|
||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "RX: '{0}'",
|
||||
ShowHexResponse ? ComTextHelper.GetEscapedText(args.Text) : args.Text);
|
||||
|
||||
Debug.Console(1, this, "RX: '{0}'", args.Text);
|
||||
|
||||
try
|
||||
{
|
||||
if (args.Text.IndexOf("Welcome to the Tesira Text Protocol Server...") > -1)
|
||||
{
|
||||
// Indicates a new TTP session
|
||||
|
||||
SubscribeToAttributes();
|
||||
}
|
||||
else if (args.Text.IndexOf("publishToken") > -1)
|
||||
{
|
||||
// response is from a subscribed attribute
|
||||
|
||||
string pattern = "! \"publishToken\":[\"](.*)[\"] \"value\":(.*)";
|
||||
|
||||
Match match = Regex.Match(args.Text, pattern);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
|
||||
string key;
|
||||
|
||||
string customName;
|
||||
|
||||
string value;
|
||||
|
||||
customName = match.Groups[1].Value;
|
||||
|
||||
// Finds the key (everything before the '~' character
|
||||
key = customName.Substring(0, customName.IndexOf("~", 0) - 1);
|
||||
|
||||
value = match.Groups[2].Value;
|
||||
|
||||
foreach (KeyValuePair<string, TesiraForteLevelControl> controlPoint in LevelControlPoints)
|
||||
{
|
||||
if (customName == controlPoint.Value.LevelCustomName || customName == controlPoint.Value.MuteCustomName)
|
||||
{
|
||||
controlPoint.Value.ParseSubscriptionMessage(customName, value);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// same for dialers
|
||||
/// same for switchers
|
||||
|
||||
}
|
||||
else if (args.Text.IndexOf("+OK") > -1)
|
||||
{
|
||||
if (args.Text == "+OK" || args.Text.IndexOf("list\":") > -1 ) // Check for a simple "+OK" only 'ack' repsonse or a list response and ignore
|
||||
return;
|
||||
|
||||
// response is not from a subscribed attribute. From a get/set/toggle/increment/decrement command
|
||||
|
||||
if (!CommandQueue.IsEmpty)
|
||||
{
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
// Expected response belongs to a child class
|
||||
QueuedCommand tempCommand = (QueuedCommand)CommandQueue.TryToDequeue();
|
||||
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
|
||||
|
||||
tempCommand.ControlPoint.ParseGetMessage(tempCommand.AttributeCode, args.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Expected response belongs to this class
|
||||
string temp = (string)CommandQueue.TryToDequeue();
|
||||
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
|
||||
|
||||
}
|
||||
|
||||
if (CommandQueue.IsEmpty)
|
||||
CommandQueueInProgress = false;
|
||||
else
|
||||
SendNextQueuedCommand();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (args.Text.IndexOf("-ERR") > -1)
|
||||
{
|
||||
// Error response
|
||||
|
||||
switch (args.Text)
|
||||
{
|
||||
case "-ERR ALREADY_SUBSCRIBED":
|
||||
{
|
||||
ResetSubscriptionTimer();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Debug.Console(0, this, "Error From DSP: '{0}'", args.Text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP (with delimiter appended)
|
||||
/// </summary>
|
||||
/// <param name="s">Command to send</param>
|
||||
public void SendLine(string s)
|
||||
{
|
||||
Debug.Console(1, this, "TX: '{0}'", s);
|
||||
Communication.SendText(s + "\x0a");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command from a child module to the queue
|
||||
/// </summary>
|
||||
/// <param name="command">Command object from child module</param>
|
||||
public void EnqueueCommand(QueuedCommand commandToEnqueue)
|
||||
{
|
||||
CommandQueue.Enqueue(commandToEnqueue);
|
||||
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
|
||||
|
||||
if(!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a raw string command to the queue
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
public void EnqueueCommand(string command)
|
||||
{
|
||||
CommandQueue.Enqueue(command);
|
||||
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the next queued command to the DSP
|
||||
/// </summary>
|
||||
void SendNextQueuedCommand()
|
||||
{
|
||||
//Debug.Console(2, this, "Attempting to send next queued command. CommandQueueInProgress: {0} Communication isConnected: {1}", CommandQueueInProgress, Communication.IsConnected);
|
||||
|
||||
//if (CommandQueue.IsEmpty)
|
||||
// CommandQueueInProgress = false;
|
||||
|
||||
//Debug.Console(1, this, "CommandQueue has {0} Elements:\n", CommandQueue.Count);
|
||||
|
||||
//foreach (object o in CommandQueue)
|
||||
//{
|
||||
// if (o is string)
|
||||
// Debug.Console(1, this, "{0}", o);
|
||||
// else if(o is QueuedCommand)
|
||||
// {
|
||||
// var item = (QueuedCommand)o;
|
||||
// Debug.Console(1, this, "{0}", item.Command);
|
||||
// }
|
||||
//}
|
||||
|
||||
//Debug.Console(1, this, "End of CommandQueue");
|
||||
|
||||
if (Communication.IsConnected && !CommandQueue.IsEmpty)
|
||||
{
|
||||
CommandQueueInProgress = true;
|
||||
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
QueuedCommand nextCommand = new QueuedCommand();
|
||||
|
||||
nextCommand = (QueuedCommand)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand.Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nextCommand = (string)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to execute a preset
|
||||
/// </summary>
|
||||
/// <param name="name">Preset Name</param>
|
||||
public override void RunPreset(string name)
|
||||
{
|
||||
SendLine(string.Format("DEVICE recallPreset {0}", name));
|
||||
}
|
||||
|
||||
public class QueuedCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string AttributeCode { get; set; }
|
||||
public TesiraForteControlPoint ControlPoint { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
public class BiampTesiraForteDspFactory : EssentialsDeviceFactory<BiampTesiraForteDsp>
|
||||
{
|
||||
public BiampTesiraForteDspFactory()
|
||||
{
|
||||
TypeNames = new List<string>() { "biamptesira" };
|
||||
}
|
||||
|
||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||
{
|
||||
Debug.Console(1, "Factory Attempting to create new BiampTesira Device");
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<BiampTesiraFortePropertiesConfig>(
|
||||
dc.Properties.ToString());
|
||||
return new BiampTesiraForteDsp(dc.Key, dc.Name, comm, props);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
|
||||
// QUESTIONS:
|
||||
//
|
||||
// When subscribing, just use the Instance ID for Custom Name?
|
||||
|
||||
// Verbose on subscriptions?
|
||||
|
||||
// Example subscription feedback responses
|
||||
// ! "publishToken":"name" "value":-77.0
|
||||
// ! "myLevelName" -77
|
||||
|
||||
public class BiampTesiraForteDsp : DspBase
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
public new Dictionary<string, TesiraForteLevelControl> LevelControlPoints { get; private set; }
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
private CTimer SubscriptionTimer;
|
||||
|
||||
private CrestronQueue CommandQueue;
|
||||
|
||||
private bool CommandQueueInProgress = false;
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shows received lines as hex
|
||||
/// </summary>
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public BiampTesiraForteDsp(string key, string name, IBasicCommunication comm,
|
||||
BiampTesiraFortePropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
CommandQueue = new CrestronQueue(100);
|
||||
|
||||
Communication = comm;
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// This instance uses IP control
|
||||
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This instance uses RS-232 control
|
||||
}
|
||||
PortGather = new CommunicationGather(Communication, "\x0d\x0a");
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication,
|
||||
props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
//#warning Need to deal with this poll string
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000,
|
||||
"SESSION get aliases\x0d\x0a");
|
||||
}
|
||||
|
||||
LevelControlPoints = new Dictionary<string, TesiraForteLevelControl>();
|
||||
|
||||
foreach (KeyValuePair<string, BiampTesiraForteLevelControlBlockConfig> block in props.LevelControlBlocks)
|
||||
{
|
||||
this.LevelControlPoints.Add(block.Key, new TesiraForteLevelControl(block.Key, block.Value, this));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange +=
|
||||
(o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
// Tasks on connect
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cleanup items from this session
|
||||
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer.Stop();
|
||||
SubscriptionTimer = null;
|
||||
}
|
||||
|
||||
isSubscribed = false;
|
||||
CommandQueue.Clear();
|
||||
CommandQueueInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the subscription process to the DSP
|
||||
/// </summary>
|
||||
private void SubscribeToAttributes()
|
||||
{
|
||||
SendLine("SESSION set verbose true");
|
||||
|
||||
foreach (KeyValuePair<string, TesiraForteLevelControl> level in LevelControlPoints)
|
||||
{
|
||||
level.Value.Subscribe();
|
||||
}
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
|
||||
ResetSubscriptionTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets or Sets the subscription timer
|
||||
/// </summary>
|
||||
private void ResetSubscriptionTimer()
|
||||
{
|
||||
isSubscribed = true;
|
||||
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer = new CTimer(o => SubscribeToAttributes(), 30000);
|
||||
SubscriptionTimer.Reset();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a response message from the DSP
|
||||
/// </summary>
|
||||
/// <param name="dev"></param>
|
||||
/// <param name="args"></param>
|
||||
private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "RX: '{0}'",
|
||||
ShowHexResponse ? ComTextHelper.GetEscapedText(args.Text) : args.Text);
|
||||
|
||||
Debug.Console(1, this, "RX: '{0}'", args.Text);
|
||||
|
||||
try
|
||||
{
|
||||
if (args.Text.IndexOf("Welcome to the Tesira Text Protocol Server...") > -1)
|
||||
{
|
||||
// Indicates a new TTP session
|
||||
|
||||
SubscribeToAttributes();
|
||||
}
|
||||
else if (args.Text.IndexOf("publishToken") > -1)
|
||||
{
|
||||
// response is from a subscribed attribute
|
||||
|
||||
string pattern = "! \"publishToken\":[\"](.*)[\"] \"value\":(.*)";
|
||||
|
||||
Match match = Regex.Match(args.Text, pattern);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
|
||||
string key;
|
||||
|
||||
string customName;
|
||||
|
||||
string value;
|
||||
|
||||
customName = match.Groups[1].Value;
|
||||
|
||||
// Finds the key (everything before the '~' character
|
||||
key = customName.Substring(0, customName.IndexOf("~", 0) - 1);
|
||||
|
||||
value = match.Groups[2].Value;
|
||||
|
||||
foreach (KeyValuePair<string, TesiraForteLevelControl> controlPoint in LevelControlPoints)
|
||||
{
|
||||
if (customName == controlPoint.Value.LevelCustomName ||
|
||||
customName == controlPoint.Value.MuteCustomName)
|
||||
{
|
||||
controlPoint.Value.ParseSubscriptionMessage(customName, value);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// same for dialers
|
||||
/// same for switchers
|
||||
|
||||
}
|
||||
else if (args.Text.IndexOf("+OK") > -1)
|
||||
{
|
||||
if (args.Text == "+OK" || args.Text.IndexOf("list\":") > -1)
|
||||
// Check for a simple "+OK" only 'ack' repsonse or a list response and ignore
|
||||
return;
|
||||
|
||||
// response is not from a subscribed attribute. From a get/set/toggle/increment/decrement command
|
||||
|
||||
if (!CommandQueue.IsEmpty)
|
||||
{
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
// Expected response belongs to a child class
|
||||
QueuedCommand tempCommand = (QueuedCommand) CommandQueue.TryToDequeue();
|
||||
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
|
||||
|
||||
tempCommand.ControlPoint.ParseGetMessage(tempCommand.AttributeCode, args.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Expected response belongs to this class
|
||||
string temp = (string) CommandQueue.TryToDequeue();
|
||||
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
|
||||
|
||||
}
|
||||
|
||||
if (CommandQueue.IsEmpty)
|
||||
CommandQueueInProgress = false;
|
||||
else
|
||||
SendNextQueuedCommand();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (args.Text.IndexOf("-ERR") > -1)
|
||||
{
|
||||
// Error response
|
||||
|
||||
switch (args.Text)
|
||||
{
|
||||
case "-ERR ALREADY_SUBSCRIBED":
|
||||
{
|
||||
ResetSubscriptionTimer();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Debug.Console(0, this, "Error From DSP: '{0}'", args.Text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP (with delimiter appended)
|
||||
/// </summary>
|
||||
/// <param name="s">Command to send</param>
|
||||
public void SendLine(string s)
|
||||
{
|
||||
Debug.Console(1, this, "TX: '{0}'", s);
|
||||
Communication.SendText(s + "\x0a");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command from a child module to the queue
|
||||
/// </summary>
|
||||
/// <param name="command">Command object from child module</param>
|
||||
public void EnqueueCommand(QueuedCommand commandToEnqueue)
|
||||
{
|
||||
CommandQueue.Enqueue(commandToEnqueue);
|
||||
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a raw string command to the queue
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
public void EnqueueCommand(string command)
|
||||
{
|
||||
CommandQueue.Enqueue(command);
|
||||
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the next queued command to the DSP
|
||||
/// </summary>
|
||||
private void SendNextQueuedCommand()
|
||||
{
|
||||
//Debug.Console(2, this, "Attempting to send next queued command. CommandQueueInProgress: {0} Communication isConnected: {1}", CommandQueueInProgress, Communication.IsConnected);
|
||||
|
||||
//if (CommandQueue.IsEmpty)
|
||||
// CommandQueueInProgress = false;
|
||||
|
||||
//Debug.Console(1, this, "CommandQueue has {0} Elements:\n", CommandQueue.Count);
|
||||
|
||||
//foreach (object o in CommandQueue)
|
||||
//{
|
||||
// if (o is string)
|
||||
// Debug.Console(1, this, "{0}", o);
|
||||
// else if(o is QueuedCommand)
|
||||
// {
|
||||
// var item = (QueuedCommand)o;
|
||||
// Debug.Console(1, this, "{0}", item.Command);
|
||||
// }
|
||||
//}
|
||||
|
||||
//Debug.Console(1, this, "End of CommandQueue");
|
||||
|
||||
if (Communication.IsConnected && !CommandQueue.IsEmpty)
|
||||
{
|
||||
CommandQueueInProgress = true;
|
||||
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
QueuedCommand nextCommand = new QueuedCommand();
|
||||
|
||||
nextCommand = (QueuedCommand) CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand.Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nextCommand = (string) CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to execute a preset
|
||||
/// </summary>
|
||||
/// <param name="name">Preset Name</param>
|
||||
public void RunPreset(string name)
|
||||
{
|
||||
SendLine(string.Format("DEVICE recallPreset {0}", name));
|
||||
}
|
||||
|
||||
public class QueuedCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string AttributeCode { get; set; }
|
||||
public TesiraForteControlPoint ControlPoint { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
public class BiampTesiraForteDspFactory : EssentialsDeviceFactory<BiampTesiraForteDsp>
|
||||
{
|
||||
public BiampTesiraForteDspFactory()
|
||||
{
|
||||
TypeNames = new List<string>() {"biamptesira"};
|
||||
}
|
||||
|
||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||
{
|
||||
Debug.Console(1, "Factory Attempting to create new BiampTesira Device");
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<BiampTesiraFortePropertiesConfig>(
|
||||
dc.Properties.ToString());
|
||||
return new BiampTesiraForteDsp(dc.Key, dc.Name, comm, props);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,18 +15,19 @@ namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
|
||||
public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
||||
|
||||
public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
public abstract void RunPreset(string name);
|
||||
|
||||
public DspBase(string key, string name) :
|
||||
base(key, name) { }
|
||||
public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
public DspBase(string key, string name) :
|
||||
base(key, name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// in audio call feedback
|
||||
|
||||
// VOIP
|
||||
// Phone dialer
|
||||
// Phone dialer
|
||||
|
||||
}
|
||||
|
||||
// Fusion
|
||||
|
||||
Reference in New Issue
Block a user