private static MediaPlayerState BuildOne(IBMDSwitcherMediaPlayer props, AtemStateBuilderSettings updateSettings, bool hasClips)
        {
            var state = new MediaPlayerState();

            if (hasClips)
            {
                state.ClipStatus = new MediaPlayerState.ClipStatusState();
            }

            props.GetSource(out _BMDSwitcherMediaPlayerSourceType type, out uint index);
            state.Source.SourceType  = AtemEnumMaps.MediaPlayerSourceMap.FindByValue(type);
            state.Source.SourceIndex = index;

            if (state.ClipStatus != null)
            {
                props.GetPlaying(out int playing);
                state.ClipStatus.Playing = playing != 0;
                props.GetLoop(out int loop);
                state.ClipStatus.Loop = loop != 0;

                if (updateSettings.TrackMediaClipFrames)
                {
                    props.GetAtBeginning(out int atBegining);
                    state.ClipStatus.AtBeginning = atBegining != 0;
                    props.GetClipFrame(out uint clipFrame);
                    state.ClipStatus.ClipFrame = clipFrame;
                }
            }

            return(state);
        }
        public static IReadOnlyList <MediaPlayerState> Build(IBMDSwitcher switcher, AtemStateBuilderSettings updateSettings, bool hasClips)
        {
            var iterator = AtemSDKConverter.CastSdk <IBMDSwitcherMediaPlayerIterator>(switcher.CreateIterator);

            return(AtemSDKConverter.IterateList <IBMDSwitcherMediaPlayer, MediaPlayerState>(iterator.Next,
                                                                                            (media, id) => BuildOne(media, updateSettings, hasClips)));
        }
Esempio n. 3
0
        public AtemSdkClientWrapper(string address, AtemStateBuilderSettings updateSettings, int id)
        {
            var logRepository = LogManager.GetRepository(Assembly.GetExecutingAssembly());

            XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
            if (!logRepository.Configured) // Default to all on the console
            {
                BasicConfigurator.Configure(logRepository);
            }

            Id = id;

            _updateSettings = updateSettings;

            _switcherDiscovery = new CBMDSwitcherDiscovery();
            Assert.NotNull(_switcherDiscovery);

            _BMDSwitcherConnectToFailure failReason = 0;

            try
            {
                _switcherDiscovery.ConnectTo(address, out _sdkSwitcher, out failReason);
            }
            catch (COMException)
            {
                throw new Exception($"SDK Connection failure: {failReason}");
            }

            //_sdkSwitcher.AddCallback(new SwitcherConnectionMonitor()); // TODO - make this monitor work better!

            _sdkState = new AtemSDKStateMonitor(_sdkSwitcher);
            _sdkState.OnStateChange += (s) => OnSdkStateChange?.Invoke(s);
        }
Esempio n. 4
0
        public AtemTestHelper(AtemSdkClientWrapper client, ITestOutputHelper output, AtemMockServer mockServer, AtemStateBuilderSettings stateSettings)
        {
            _mockServer   = mockServer;
            SdkClient     = client;
            Output        = output;
            StateSettings = stateSettings;

            SyncStates();
            _mockServer.LibReceive += LibAtemReceive;

            AssertStatesMatch();
        }
Esempio n. 5
0
        private void RunTest(string caseId)
        {
            if (caseId == "")
            {
                return;
            }

            var commandData = DumpParser.BuildCommands(DeviceTestCases.Version, caseId);

            /*
             * var result = new List<string>();
             * foreach (byte[] payload in commandData)
             * {
             *  foreach (ParsedCommand rawCmd in ReceivedPacket.ParseCommands(payload))
             *  {
             *      if (CommandParser.Parse(caseId.Item1, rawCmd) == null)
             *      {
             *          _output.WriteLine("{0} - {1}", rawCmd.Name, rawCmd.BodyLength);
             *          result.Add(rawCmd.Name);
             *      }
             *  }
             * }
             * Assert.Empty(result);
             * // */


            using var server = new AtemMockServer("127.0.0.1", commandData, DeviceTestCases.Version);
            var stateSettings = new AtemStateBuilderSettings();

            using var helper = new AtemSdkClientWrapper("127.0.0.1", stateSettings, 1);

            var libAtemState = AtemTestHelper.SanitiseStateIncompabalities(DeviceTestCases.Version,
                                                                           GetLibAtemState(stateSettings, "127.0.0.1"));
            var sdkState = helper.BuildState();

            List <string> before = AtemStateComparer.AreEqual(sdkState, libAtemState);

            if (before.Count != 0 && _output != null)
            {
                _output.WriteLine("state mismatch:");
                before.ForEach(_output.WriteLine);
            }
            Assert.Empty(before);
        }
        // public AtemClient LibAtemClient { get; }

        // private bool _isDisposing;
        // private bool _libAtemConnected;

        public AtemMockServerPoolItem(string caseId, AtemStateBuilderSettings builderSettings, string bindIp)
        {
            _builderSettings = builderSettings;
            _bindIp          = bindIp;
            _sdkClients      = new Queue <AtemSdkClientWrapper>();
            _updatingClients = new List <AtemSdkClientWrapper>();
            _nextSdkId       = 0;

            List <byte[]> payloads = DumpParser.BuildCommands(DeviceTestCases.Version, caseId);

            // IReadOnlyList<ICommand> commands = DumpParser.ParseToCommands(DeviceTestCases.Version, payloads);

            // Build the device profile
            // var deviceProfileBuilder = new DeviceProfile.DeviceProfileHandler();
            // deviceProfileBuilder.HandleCommands(null, commands);
            // DeviceProfile = deviceProfileBuilder.Profile;

            // Build a default state
            // var state = new AtemState();
            // commands.ForEach(cmd => AtemStateBuilder.Update(state, cmd, builderSettings));
            // DefaultState = state;

            Server = new AtemMockServer(bindIp, payloads, DeviceTestCases.Version);

            /*
             * var connectionEvent = new AutoResetEvent(false);
             * LibAtemClient = new AtemClient(bindIp, false);
             * LibAtemClient.OnDisconnect += o => { Assert.True(_isDisposing, "LibAtem: Disconnect before disposing"); };
             * LibAtemClient.OnConnection += o =>
             * {
             *  Assert.False(_libAtemConnected, "LibAtem: Got reconnect");
             *  _libAtemConnected = true;
             *  connectionEvent.Set();
             * };
             * LibAtemClient.Connect();
             *
             * //SdkClient = new AtemSdkClientWrapper(bindIp", StateSettings);
             *
             * Assert.True(connectionEvent.WaitOne(TimeSpan.FromSeconds(3)), "LibAtem: Connection attempt timed out");
             */
        }
        public static void Build(AtemState state, IBMDSwitcherCameraControl camera, AtemStateBuilderSettings updateSettings)
        {
            camera.GetPeriodicFlushInterval(out uint interval);
            state.CameraControl.PeriodicFlushInterval = interval;

            IBMDSwitcherCameraControlParameterIterator iterator =
                AtemSDKConverter.CastSdk <IBMDSwitcherCameraControlParameterIterator>(camera.CreateIterator);
            uint lastDevice    = uint.MaxValue;
            uint lastCategory  = 0u;
            uint lastParameter = 0u;

            for (iterator.Next(out var device, out var category, out var parameter);
                 ;
                 iterator.Next(out device, out category, out parameter))
            {
                if (device == lastDevice && category == lastCategory && parameter == lastParameter)
                {
                    break;
                }

                lastDevice    = device;
                lastCategory  = category;
                lastParameter = parameter;

                if (device == 0)
                {
                    continue;
                }

                if (!state.CameraControl.Cameras.TryGetValue(device, out CameraControlState.CameraState cState))
                {
                    cState = state.CameraControl.Cameras[device] = new CameraControlState.CameraState();
                }

                CameraControlGetCommand cmd = BuildCommand(camera, device, category, parameter);
                CameraControlUtil.ApplyToState(cState, cmd, updateSettings.IgnoreUnknownCameraControlProperties);
            }
        }
Esempio n. 8
0
        /*
         * [Fact]
         * public void TestStateReal()
         * {
         *  var stateSettings = new AtemStateBuilderSettings();
         *  using var helper = new AtemSdkClientWrapper("10.42.13.95", stateSettings);
         *
         *  var libAtemState = GetLibAtemState(stateSettings, "10.42.13.95");
         *
         *  List<string> before = AtemStateComparer.AreEqual(helper.State, libAtemState);
         *  if (before.Count != 0 && _output != null)
         *  {
         *      _output.WriteLine("state mismatch:");
         *      before.ForEach(_output.WriteLine);
         *  }
         *  Assert.Empty(before);
         * }
         */

        private AtemState GetLibAtemState(AtemStateBuilderSettings stateSettings, string address)
        {
            using var client = new AtemClient(address, false);
            var state = new AtemState();

            AutoResetEvent handshakeEvent    = new AutoResetEvent(false);
            bool           handshakeFinished = false;

            client.OnReceive += (o, cmds) =>
            {
                cmds.ForEach(cmd => AtemStateBuilder.Update(state, cmd, stateSettings));

                if (!handshakeFinished && cmds.Any(c => c is InitializationCompleteCommand))
                {
                    handshakeEvent.Set();
                    handshakeFinished = true;
                }
            };
            client.Connect();
            Assert.True(handshakeEvent.WaitOne(5000));

            return(state);
        }
        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);
        }
 public AtemServerClientPool()
 {
     _pool         = new Dictionary <string, AtemMockServerPoolItem>();
     StateSettings = new AtemStateBuilderSettings();
 }