Skip to content

Commit

Permalink
feat: Atem HD8 audio routing
Browse files Browse the repository at this point in the history
  • Loading branch information
Julusian committed Jul 14, 2023
1 parent 3d866ef commit 091a0a8
Show file tree
Hide file tree
Showing 12 changed files with 349 additions and 22 deletions.
103 changes: 103 additions & 0 deletions LibAtem.MockTests/AudioRouting/TestAudioRoutingOutput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using BMDSwitcherAPI;
using LibAtem.Commands.AudioRouting;
using LibAtem.MockTests.SdkState;
using LibAtem.MockTests.Util;
using LibAtem.State;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using Xunit.Abstractions;

namespace LibAtem.MockTests.AudioRouting
{
[Collection("ServerClientPool")]
public class TestAudioRoutingOutput
{
private readonly ITestOutputHelper _output;
private readonly AtemServerClientPool _pool;

public TestAudioRoutingOutput(ITestOutputHelper output, AtemServerClientPool pool)
{
_output = output;
_pool = pool;
}

private static Dictionary<uint, IBMDSwitcherAudioRoutingOutput> GetRoutableOutputs(AtemMockServerWrapper helper)
{
var res = new Dictionary<uint, IBMDSwitcherAudioRoutingOutput>();

var outputIterator = AtemSDKConverter.CastSdk<IBMDSwitcherAudioRoutingOutputIterator>(helper.SdkClient.SdkSwitcher.CreateIterator);
var outputsList = AtemSDKConverter.ToList<IBMDSwitcherAudioRoutingOutput>(outputIterator.Next);

foreach (var output in outputsList)
{
output.GetId(out uint id);
res[id] = output;
}

return res;
}

[Fact]
public void TestSourceId()
{
var handler = CommandGenerator.CreateAutoCommandHandler<AudioRoutingOutputSetCommand, AudioRoutingOutputGetCommand>("SourceId");
AtemMockServerWrapper.Each(_output, _pool, handler, DeviceTestCases.AudioRouting, helper =>
{
Dictionary<uint, IBMDSwitcherAudioRoutingOutput> allOutputs = GetRoutableOutputs(helper);
List<uint> chosenIds = Randomiser.SelectionOfGroup(allOutputs.Keys.ToList()).ToList();
foreach (var outputId in chosenIds)
{
IBMDSwitcherAudioRoutingOutput output = allOutputs[outputId];
Assert.NotNull(output);
AtemState stateBefore = helper.Helper.BuildLibState();
Assert.NotNull(stateBefore.AudioRouting);
for (int i = 0; i < 5; i++)
{
uint sourceId = Randomiser.RangeInt(65535);
stateBefore.AudioRouting.Outputs[outputId].SourceId = sourceId;
helper.SendAndWaitForChange(stateBefore, () =>
{
output.SetSource(sourceId);
});
}
}
});
}

[Fact]
public void TestName()
{
var handler = CommandGenerator.CreateAutoCommandHandler<AudioRoutingOutputSetCommand, AudioRoutingOutputGetCommand>("Name");
AtemMockServerWrapper.Each(_output, _pool, handler, DeviceTestCases.AudioRouting, helper =>
{
Dictionary<uint, IBMDSwitcherAudioRoutingOutput> allOutputs = GetRoutableOutputs(helper);
List<uint> chosenIds = Randomiser.SelectionOfGroup(allOutputs.Keys.ToList()).ToList();
foreach (var outputId in chosenIds)
{
IBMDSwitcherAudioRoutingOutput output = allOutputs[outputId];
Assert.NotNull(output);
AtemState stateBefore = helper.Helper.BuildLibState();
Assert.NotNull(stateBefore.AudioRouting);
for (int i = 0; i < 5; i++)
{
string name = Randomiser.String(64);
stateBefore.AudioRouting.Outputs[outputId].Name = name;
helper.SendAndWaitForChange(stateBefore, () =>
{
output.SetName(name);
});
}
}
});
}
}
}
72 changes: 72 additions & 0 deletions LibAtem.MockTests/AudioRouting/TestAudioRoutingSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using BMDSwitcherAPI;
using LibAtem.Commands.AudioRouting;
using LibAtem.MockTests.SdkState;
using LibAtem.MockTests.Util;
using LibAtem.State;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using Xunit.Abstractions;

namespace LibAtem.MockTests.AudioRouting
{
[Collection("ServerClientPool")]
public class TestAudioRoutingSource
{
private readonly ITestOutputHelper _output;
private readonly AtemServerClientPool _pool;

public TestAudioRoutingSource(ITestOutputHelper output, AtemServerClientPool pool)
{
_output = output;
_pool = pool;
}

private static Dictionary<uint, IBMDSwitcherAudioRoutingSource> GetRoutableSources(AtemMockServerWrapper helper)
{
var res = new Dictionary<uint, IBMDSwitcherAudioRoutingSource>();

var sourceIterator = AtemSDKConverter.CastSdk<IBMDSwitcherAudioRoutingSourceIterator>(helper.SdkClient.SdkSwitcher.CreateIterator);
var sourceList = AtemSDKConverter.ToList<IBMDSwitcherAudioRoutingSource>(sourceIterator.Next);

foreach (var source in sourceList)
{
source.GetId(out uint id);
res[id] = source;
}

return res;
}

[Fact]
public void TestName()
{
var handler = CommandGenerator.CreateAutoCommandHandler<AudioRoutingSourceSetCommand, AudioRoutingSourceGetCommand>("Name");
AtemMockServerWrapper.Each(_output, _pool, handler, DeviceTestCases.AudioRouting, helper =>
{
Dictionary<uint, IBMDSwitcherAudioRoutingSource> allSources = GetRoutableSources(helper);
List<uint> chosenIds = Randomiser.SelectionOfGroup(allSources.Keys.ToList()).ToList();
foreach (var sourceId in chosenIds)
{
IBMDSwitcherAudioRoutingSource source = allSources[sourceId];
Assert.NotNull(source);
AtemState stateBefore = helper.Helper.BuildLibState();
Assert.NotNull(stateBefore.AudioRouting);
for (int i = 0; i < 5; i++)
{
string name = Randomiser.String(64);
stateBefore.AudioRouting.Sources[sourceId].Name = name;
helper.SendAndWaitForChange(stateBefore, () =>
{
source.SetName(name);
});
}
}
});
}
}
}
7 changes: 6 additions & 1 deletion LibAtem.MockTests/DeviceTestCases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal static class DeviceTestCases
public static readonly string FourME4K = "";
public static readonly string TVSHD = "tvshd-v8.1.0";
public static readonly string TVS = "tvs-v8.1.0";
public static readonly string TVSHD8 = "";
#elif ATEM_v8_1_1
public static readonly ProtocolVersion Version = ProtocolVersion.V8_1_1;
public static readonly string MiniExtremeIso = "mini-extreme-iso-v8.6.1";
Expand All @@ -29,9 +30,10 @@ internal static class DeviceTestCases
public static readonly string FourME4K = "4me-bs4k-v8.2";
public static readonly string TVSHD = "tvshd-v8.2.0";
public static readonly string TVS = "tvs-v8.1.1";
public static readonly string TVSHD8 = "tvs-hd8-v9.0";
#endif

public static readonly string[] All = { MiniExtremeIso, Mini, Constellation, Constellation2MEHD, TwoME, TVSHD, TVS, TwoME4K, FourME4K};
public static readonly string[] All = { MiniExtremeIso, Mini, Constellation, Constellation2MEHD, TwoME, TVSHD, TVS, TwoME4K, FourME4K, TVSHD8 };
public static readonly string[] DownConvertSDMode = { TwoME };
public static readonly string[] DownConvertHDMode = { FourME4K };
public static readonly string[] AutoVideoMode = {Mini, MiniExtremeIso };
Expand Down Expand Up @@ -82,6 +84,9 @@ internal static class DeviceTestCases
public static readonly string[] ClassicAudioMonitors = { TwoME4K, FourME4K };
public static readonly string[] ClassicAudioXLRLevel = { TVSHD };

public static readonly string[] AudioRouting = { TVSHD8 };

public static readonly string[] DisplayClock = { Constellation2MEHD };

}
}
3 changes: 3 additions & 0 deletions LibAtem.MockTests/LibAtem.MockTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@
<None Update="TestFiles\Handshake\mini-v8.3.data">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="TestFiles\Handshake\tvs-hd8-v9.0.data">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="TestFiles\Handshake\tvs-v8.1.0.data">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down
31 changes: 30 additions & 1 deletion LibAtem.MockTests/SdkState/AtemEnumMaps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public static class AtemEnumMaps
public static readonly IReadOnlyDictionary<RecordingError, _BMDSwitcherRecordAVError> RecordingErrorMap;
public static readonly IReadOnlyDictionary<DisplayClockClockMode, _BMDSwitcherDisplayClockMode> DisplayClockModeMap;
public static readonly IReadOnlyDictionary<DisplayClockClockState, _BMDSwitcherDisplayClockState> DisplayClockStateMap;
public static readonly IReadOnlyDictionary<AudioChannelPair, _BMDSwitcherAudioChannelPair> AudioChannelPairMap;
public static readonly IReadOnlyDictionary<AudioInternalPortType, _BMDSwitcherAudioInternalPortType> AudioInternalPortTypeMap;
#endif

static AtemEnumMaps()
Expand Down Expand Up @@ -424,6 +426,32 @@ static AtemEnumMaps()
{DisplayClockClockState.Stopped, _BMDSwitcherDisplayClockState.bmdSwitcherDisplayClockStateStopped},
{DisplayClockClockState.Running, _BMDSwitcherDisplayClockState.bmdSwitcherDisplayClockStateRunning},
};
AudioChannelPairMap = new Dictionary<AudioChannelPair, _BMDSwitcherAudioChannelPair>
{
{AudioChannelPair.Channel1_2, _BMDSwitcherAudioChannelPair.bmdSwitcherAudioChannelPair_1_2},
{AudioChannelPair.Channel3_4, _BMDSwitcherAudioChannelPair.bmdSwitcherAudioChannelPair_3_4},
{AudioChannelPair.Channel5_6, _BMDSwitcherAudioChannelPair.bmdSwitcherAudioChannelPair_5_6},
{AudioChannelPair.Channel7_8, _BMDSwitcherAudioChannelPair.bmdSwitcherAudioChannelPair_7_8},
{AudioChannelPair.Channel9_10, _BMDSwitcherAudioChannelPair.bmdSwitcherAudioChannelPair_9_10},
{AudioChannelPair.Channel11_12, _BMDSwitcherAudioChannelPair.bmdSwitcherAudioChannelPair_11_12},
{AudioChannelPair.Channel13_14, _BMDSwitcherAudioChannelPair.bmdSwitcherAudioChannelPair_13_14},
{AudioChannelPair.Channel15_16, _BMDSwitcherAudioChannelPair.bmdSwitcherAudioChannelPair_15_16},
};
AudioInternalPortTypeMap = new Dictionary<AudioInternalPortType, _BMDSwitcherAudioInternalPortType> {

{ AudioInternalPortType.NotInternal, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeNotInternal },
{AudioInternalPortType.NoAudio, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeNoAudio },
{ AudioInternalPortType.TalkbackMix, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeTalkbackMix } ,
{AudioInternalPortType.EngineeringTalkbackMix, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeEngineeringTalkbackMix } ,
{AudioInternalPortType.ProductionTalkbackMix, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeProductionTalkbackMix} ,
{AudioInternalPortType.MediaPlayer, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeMediaPlayer },
{AudioInternalPortType.Program, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeProgram },
{AudioInternalPortType.Return, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeReturn },
{AudioInternalPortType.Monitor, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeMonitor },
{AudioInternalPortType.Madi, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeMadi},
{AudioInternalPortType.AuxOut, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeAuxOut} ,
{AudioInternalPortType.AudioAuxOut, _BMDSwitcherAudioInternalPortType. bmdSwitcherAudioInternalPortTypeAudioAuxOut }
};
#endif
}

Expand Down Expand Up @@ -506,7 +534,8 @@ public static double GetDefaultPatternSymmetry(this Pattern pattern)

foreach (_BMDSwitcherInputAvailability val in sdkInput.FindFlagComponents())
{
switch (val) {
switch (val)
{
case _BMDSwitcherInputAvailability.bmdSwitcherInputAvailabilityMixEffectBlock0:
me |= MeAvailability.Me1;
break;
Expand Down
13 changes: 8 additions & 5 deletions LibAtem.MockTests/SdkState/FairlightAudioInputStateBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ public static FairlightAudioState.InputState Build(IBMDSwitcherFairlightAudioInp
// Analog
if (props is IBMDSwitcherFairlightAnalogAudioInput analog)
{
state.Analog = new FairlightAudioState.AnalogState();
analog.GetInputLevel(out _BMDSwitcherFairlightAudioAnalogInputLevel level);
state.Analog.InputLevel = AtemEnumMaps.FairlightAnalogInputLevelMap.FindByValue(level);

analog.GetSupportedInputLevels(out _BMDSwitcherFairlightAudioAnalogInputLevel supportedLevels);
state.Analog.SupportedInputLevel = (FairlightAnalogInputLevel) supportedLevels;
if (supportedLevels != 0)
{
state.Analog = new FairlightAudioState.AnalogState();
analog.GetInputLevel(out _BMDSwitcherFairlightAudioAnalogInputLevel level);
state.Analog.InputLevel = AtemEnumMaps.FairlightAnalogInputLevelMap.FindByValue(level);

state.Analog.SupportedInputLevel = (FairlightAnalogInputLevel)supportedLevels;
}
}

#if ATEM_v8_1
Expand Down
Loading

0 comments on commit 091a0a8

Please sign in to comment.