public static AtemState Build(IBMDSwitcher switcher, AtemStateBuilderSettings updateSettings) { var state = new AtemState(); switcher.GetProductName(out string productName); state.Info.ProductName = productName; switcher.GetVideoMode(out _BMDSwitcherVideoMode videoMode); state.Settings.VideoMode = AtemEnumMaps.VideoModesMap.FindByValue(videoMode); #if !ATEM_v8_1 switcher.GetTimeCodeMode(out _BMDSwitcherTimeCodeMode timeCodeMode); if (timeCodeMode != 0) { state.Settings.TimeCodeMode = AtemEnumMaps.TimeCodeModeMap.FindByValue(timeCodeMode); } #endif switcher.GetTimeCodeLocked(out int locked); state.Info.TimecodeLocked = locked != 0; switcher.GetTimeCode(out byte hours, out byte minutes, out byte seconds, out byte frames, out int dropFrame); state.Info.LastTimecode = new Timecode { Hour = hours, Minute = minutes, Second = seconds, Frame = frames, DropFrame = dropFrame != 0 }; switcher.GetAreOutputsConfigurable(out int configurable); state.Info.OnlyConfigurableOutputs = configurable != 0; state.Info.HasCameraControl = switcher is IBMDSwitcherCameraControl; state.Info.AdvancedChromaKeyers = MixEffectStateBuilder.SupportsAdvancedChromaKeyers(switcher); try { switcher.Get3GSDIOutputLevel(out _BMDSwitcher3GSDIOutputLevel outputLevel); state.Settings.SDI3GLevel = AtemEnumMaps.SDI3GOutputLevelMap.FindByValue(outputLevel); } catch (Exception) { // This call fails on models which dont do 3g sdi state.Settings.SDI3GLevel = 0; } try { switcher.GetSuperSourceCascade(out int cascade); state.Settings.SuperSourceCascade = cascade != 0; } catch (Exception) { // This call fails on models which dont have multiple ssrc state.Settings.SuperSourceCascade = false; } switcher.GetPowerStatus(out _BMDSwitcherPowerStatus powerStatus); state.Power = new[] { powerStatus.HasFlag(_BMDSwitcherPowerStatus.bmdSwitcherPowerStatusSupply1), powerStatus.HasFlag(_BMDSwitcherPowerStatus.bmdSwitcherPowerStatusSupply2), }; bool supportsDownConvert = true; bool supportsMultiviewer = true; var modes = new List <VideoModeInfo>(); var allModes = Enum.GetValues(typeof(_BMDSwitcherVideoMode)).OfType <_BMDSwitcherVideoMode>().ToArray(); foreach (_BMDSwitcherVideoMode mode in allModes) { switcher.DoesSupportVideoMode(mode, out int supported); if (supported == 0) { continue; } switcher.DoesVideoModeChangeRequireReconfiguration(mode, out int requiresReconfig); var multiviewModes = new List <VideoMode>(); if (supportsMultiviewer) { try { foreach (_BMDSwitcherVideoMode mvMode in allModes) { switcher.DoesSupportMultiViewVideoMode(mode, mvMode, out int mvSupported); if (mvSupported != 0) { multiviewModes.Add(AtemEnumMaps.VideoModesMap.FindByValue(mvMode)); } } } catch (NotImplementedException) { supportsMultiviewer = false; } } var downConvertModes = new List <VideoMode>(); if (supportsDownConvert) { try { foreach (_BMDSwitcherVideoMode dcMode in allModes) { switcher.DoesSupportDownConvertedHDVideoMode(mode, dcMode, out int convertSupported); if (convertSupported != 0) { downConvertModes.Add(AtemEnumMaps.VideoModesMap.FindByValue(dcMode)); } } } catch (NotImplementedException) { supportsDownConvert = false; } } modes.Add(new VideoModeInfo { Mode = AtemEnumMaps.VideoModesMap.FindByValue(mode), RequiresReconfig = requiresReconfig != 0, MultiviewModes = multiviewModes.ToArray(), DownConvertModes = downConvertModes.ToArray(), }); } state.Info.SupportedVideoModes = modes.OrderBy(s => s.Mode).ToList(); if (supportsMultiviewer) { foreach (VideoModeInfo mode in state.Info.SupportedVideoModes) { switcher.GetMultiViewVideoMode(AtemEnumMaps.VideoModesMap[mode.Mode], out _BMDSwitcherVideoMode mvMode); state.Settings.MultiviewVideoModes[mode.Mode] = AtemEnumMaps.VideoModesMap.FindByValue(mvMode); } } if (supportsDownConvert) { foreach (VideoModeInfo mode in state.Info.SupportedVideoModes) { switcher.GetDownConvertedHDVideoMode(AtemEnumMaps.VideoModesMap[mode.Mode], out _BMDSwitcherVideoMode dcMode); state.Settings.DownConvertVideoModes[mode.Mode] = AtemEnumMaps.VideoModesMap.FindByValue(dcMode); } } try { switcher.GetMethodForDownConvertedSD(out _BMDSwitcherDownConversionMethod downConvertMethod); state.Settings.DownConvertMode = AtemEnumMaps.SDDownconvertModesMap.FindByValue(downConvertMethod); } catch (Exception) { // Not supported } switcher.DoesSupportAutoVideoMode(out int autoModeSupported); state.Info.SupportsAutoVideoMode = autoModeSupported != 0; if (state.Info.SupportsAutoVideoMode) { switcher.GetAutoVideoMode(out int autoVideoMode); state.Settings.AutoVideoMode = autoVideoMode != 0; switcher.GetAutoVideoModeDetected(out int detected); state.Settings.DetectedVideoMode = detected != 0; } DveInfo(state, switcher); SourceStateBuilder.Build(state, switcher); Hyperdecks(state, switcher); SerialPorts(state, switcher); Macros(state.Macros, switcher); MediaPoolStateBuilder.Build(state.MediaPool, switcher); MixMinusOutputs(state, switcher); StreamingStateBuilder.Build(state, switcher); RecordingStateBuilder.Build(state, switcher); state.DownstreamKeyers = DownstreamKeyerStateBuilder.Build(switcher); state.MediaPlayers = MediaPlayerStateBuilder.Build(switcher, updateSettings, state.MediaPool.Clips.Count > 0); state.MixEffects = MixEffectStateBuilder.Build(switcher); MultiViewerStateBuilder.Build(switcher, state); if (switcher is IBMDSwitcherFairlightAudioMixer fairlight) { state.Fairlight = FairlightAudioMixerStateBuilder.Build(fairlight); } if (switcher is IBMDSwitcherAudioMixer audioMixer) { state.Audio = AudioStateBuilder.Build(audioMixer); } #if !ATEM_v8_1 TalkbackStateBuilder.Build(state, switcher); #endif if (switcher is IBMDSwitcherCameraControl camera) { CameraControlBuilder.Build(state, camera, updateSettings); } return(state); }