public void TestPeriodicFlushInterval()
        {
            var handler =
                CommandGenerator.CreateAutoCommandHandler <CameraControlSettingsSetCommand, CameraControlSettingsGetCommand>("Interval", true);

            AtemMockServerWrapper.Each(_output, _pool, handler, DeviceTestCases.CameraControl, helper =>
            {
                helper.Helper.StateSettings.IgnoreUnknownCameraControlProperties = true;
                IBMDSwitcherCameraControl camera = helper.SdkClient.SdkSwitcher as IBMDSwitcherCameraControl;
                Assert.NotNull(camera);

                for (int i = 0; i < 5; i++)
                {
                    AtemState stateBefore = helper.Helper.BuildLibState();

                    uint interval = Randomiser.RangeInt(int.MaxValue);
                    stateBefore.CameraControl.PeriodicFlushInterval = interval;

                    helper.SendAndWaitForChange(stateBefore, () =>
                    {
                        camera.SetPeriodicFlushInterval(interval);
                    });
                }
            });
        }
        public void TestPeriodicFlushEnabled()
        {
            AtemMockServerWrapper.Each(_output, _pool, CameraCommandHandler, DeviceTestCases.CameraControl, helper =>
            {
                helper.Helper.StateSettings.IgnoreUnknownCameraControlProperties = true;
                IBMDSwitcherCameraControl camera = helper.SdkClient.SdkSwitcher as IBMDSwitcherCameraControl;
                Assert.NotNull(camera);

                using var watcher = new CameraControlReceiver(helper);

                for (int i = 0; i < 10; i++)
                {
                    AtemState stateBefore = helper.Helper.BuildLibState();

                    // Generate and send some data
                    CameraControlGetCommand cmd = new CameraControlGetCommand();
                    FillRandomData(cmd);
                    _optRefCmd         = cmd;
                    bool targetEnabled = Randomiser.Range(0, 10) >= 5;

                    if (!stateBefore.CameraControl.Cameras.ContainsKey((long)cmd.Input))
                    {
                        stateBefore.CameraControl.Cameras[(long)cmd.Input] = new CameraControlState.CameraState();
                    }

                    helper.SendAndWaitForChange(stateBefore, () =>
                    {
                        camera.SetParameterPeriodicFlushEnabled((uint)cmd.Input, cmd.Category, cmd.Parameter,
                                                                targetEnabled ? 1 : 0);
                    });

                    // Check libatem encoding
                    CameraControlGetCommand libCmd = watcher.LastCommand;
                    Assert.NotNull(libCmd);
                    AreEqual(cmd, libCmd);

                    // Pull the value out of the sdk, and ensure it is the same
                    camera.GetParameterPeriodicFlushEnabled((uint)cmd.Input, cmd.Category, cmd.Parameter,
                                                            out int resultEnabled);
                    Assert.Equal(targetEnabled, resultEnabled != 0);
                }
            });
        }
        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);
            }
        }
        public void TestSdkDecoding()
        {
            AtemMockServerWrapper.Each(_output, _pool, null, DeviceTestCases.CameraControl, helper =>
            {
                helper.Helper.StateSettings.IgnoreUnknownCameraControlProperties = true;
                IBMDSwitcherCameraControl camera = helper.SdkClient.SdkSwitcher as IBMDSwitcherCameraControl;
                Assert.NotNull(camera);

                using var watcher = new CameraControlReceiver(helper);

                for (int i = 0; i < 20; i++)
                {
                    AtemState stateBefore = helper.Helper.BuildLibState();

                    // Generate and send some data
                    CameraControlGetCommand cmd = new CameraControlGetCommand();
                    FillRandomData(cmd);

                    if (!stateBefore.CameraControl.Cameras.ContainsKey((long)cmd.Input))
                    {
                        stateBefore.CameraControl.Cameras[(long)cmd.Input] = new CameraControlState.CameraState();
                    }
                    helper.SendFromServerAndWaitForChange(stateBefore, cmd);

                    // Check libatem encoding
                    CameraControlGetCommand libCmd = watcher.LastCommand;
                    Assert.NotNull(libCmd);
                    AreEqual(cmd, libCmd);

                    // Pull the value out of the sdk, and ensure it is the same
                    CameraControlGetCommand sdkCmd =
                        CameraControlBuilder.BuildCommand(camera, (uint)cmd.Input, cmd.Category, cmd.Parameter);

                    AreEqual(cmd, sdkCmd);
                }
            });
        }
        public void TestSdkRelativeEncoding()
        {
            AtemMockServerWrapper.Each(_output, _pool, CameraCommandHandler, DeviceTestCases.CameraControl, helper =>
            {
                helper.Helper.StateSettings.IgnoreUnknownCameraControlProperties = true;
                IBMDSwitcherCameraControl camera = helper.SdkClient.SdkSwitcher as IBMDSwitcherCameraControl;
                Assert.NotNull(camera);

                using var watcher = new CameraControlReceiver(helper);

                for (int i = 0; i < 20; i++)
                {
                    AtemState stateBefore = helper.Helper.BuildLibState();

                    // Generate and send some data
                    CameraControlGetCommand refCmd = new CameraControlGetCommand();
                    FillRandomData(refCmd, CameraControlDataType.String);

                    if (!stateBefore.CameraControl.Cameras.ContainsKey((long)refCmd.Input))
                    {
                        stateBefore.CameraControl.Cameras[(long)refCmd.Input] = new CameraControlState.CameraState();
                    }

                    helper.SendFromServerAndWaitForChange(stateBefore, refCmd);
                    _prevCmd = refCmd;

                    {
                        // Pull the value out of the sdk, and ensure it is the same
                        CameraControlGetCommand sdkCmd =
                            CameraControlBuilder.BuildCommand(camera, (uint)refCmd.Input, refCmd.Category, refCmd.Parameter);

                        AreEqual(refCmd, sdkCmd);
                    }

                    CameraControlGetCommand cmd = CopyCommand(refCmd);
                    FillRandomOffsetData(cmd);

                    // Now do the sdk offset
                    helper.SendAndWaitForChange(stateBefore, () =>
                    {
                        switch (cmd.Type)
                        {
                        case CameraControlDataType.Bool:
                            {
                                IntPtr data = Randomiser.BuildSdkArray(sizeof(sbyte),
                                                                       cmd.BoolData.Select(v => v ? 1 : 0).ToArray());
                                unsafe
                                {
                                    var ptr = (int *)data.ToPointer();
                                    camera.ToggleFlags((uint)cmd.Input, cmd.Category, cmd.Parameter,
                                                       (uint)cmd.BoolData.Length, ref *ptr);
                                }
                                break;
                            }

                        case CameraControlDataType.SInt8:
                            {
                                IntPtr data = Randomiser.BuildSdkArray(sizeof(sbyte), cmd.IntData);
                                unsafe
                                {
                                    var ptr = (sbyte *)data.ToPointer();
                                    camera.OffsetInt8s((uint)cmd.Input, cmd.Category, cmd.Parameter,
                                                       (uint)cmd.IntData.Length, ref *ptr);
                                }
                                break;
                            }

                        case CameraControlDataType.SInt16:
                            {
                                IntPtr data = Randomiser.BuildSdkArray(sizeof(short), cmd.IntData);
                                unsafe
                                {
                                    var ptr = (short *)data.ToPointer();
                                    camera.OffsetInt16s((uint)cmd.Input, cmd.Category, cmd.Parameter,
                                                        (uint)cmd.IntData.Length, ref *ptr);
                                }
                                break;
                            }

                        case CameraControlDataType.SInt32:
                            {
                                IntPtr data = Randomiser.BuildSdkArray(sizeof(int), cmd.IntData);
                                unsafe
                                {
                                    var ptr = (int *)data.ToPointer();
                                    camera.OffsetInt32s((uint)cmd.Input, cmd.Category, cmd.Parameter,
                                                        (uint)cmd.IntData.Length, ref *ptr);
                                }
                                break;
                            }

                        case CameraControlDataType.SInt64:
                            {
                                IntPtr data = Randomiser.BuildSdkArray(cmd.LongData);
                                unsafe
                                {
                                    var ptr = (long *)data.ToPointer();
                                    camera.OffsetInt64s((uint)cmd.Input, cmd.Category, cmd.Parameter,
                                                        (uint)cmd.LongData.Length, ref *ptr);
                                }
                                break;
                            }

                        case CameraControlDataType.Float:
                            {
                                IntPtr data = Randomiser.BuildSdkArray(cmd.FloatData);
                                unsafe
                                {
                                    var ptr = (double *)data.ToPointer();
                                    camera.OffsetFloats((uint)cmd.Input, cmd.Category, cmd.Parameter,
                                                        (uint)cmd.FloatData.Length, ref *ptr);
                                }
                                break;
                            }

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                    });

                    var completeCmd = CopyCommand(refCmd);
                    ApplyOffsets(completeCmd, cmd);

                    // Check libatem encoding
                    CameraControlGetCommand libCmd = watcher.LastCommand;
                    Assert.NotNull(libCmd);
                    AreEqual(completeCmd, libCmd);

                    {
                        // Pull the value out of the sdk, and ensure it is the same
                        CameraControlGetCommand sdkCmd =
                            CameraControlBuilder.BuildCommand(camera, (uint)refCmd.Input, refCmd.Category, refCmd.Parameter);

                        AreEqual(completeCmd, sdkCmd);
                    }
                }
            });
        }
        public static CameraControlGetCommand BuildCommand(IBMDSwitcherCameraControl camera, uint device, uint category, uint parameter)
        {
            camera.GetParameterInfo(device, category, parameter,
                                    out _BMDSwitcherCameraControlParameterType type, out uint count);

            CameraControlDataType newType;

            switch (type)
            {
            case _BMDSwitcherCameraControlParameterType.bmdSwitcherCameraControlParameterTypeVoidBool:
                newType = CameraControlDataType.Bool;
                break;

            case _BMDSwitcherCameraControlParameterType.bmdSwitcherCameraControlParameterTypeSigned8Bit:
                newType = CameraControlDataType.SInt8;
                break;

            case _BMDSwitcherCameraControlParameterType.bmdSwitcherCameraControlParameterTypeSigned16Bit:
                newType = CameraControlDataType.SInt16;
                break;

            case _BMDSwitcherCameraControlParameterType.bmdSwitcherCameraControlParameterTypeSigned32Bit:
                newType = CameraControlDataType.SInt32;
                break;

            case _BMDSwitcherCameraControlParameterType.bmdSwitcherCameraControlParameterTypeSigned64Bit:
                newType = CameraControlDataType.SInt64;
                break;

            case _BMDSwitcherCameraControlParameterType.bmdSwitcherCameraControlParameterTypeUTF8:
                newType = CameraControlDataType.String;
                break;

            case _BMDSwitcherCameraControlParameterType.bmdSwitcherCameraControlParameterTypeFixedPoint16Bit:
                newType = CameraControlDataType.Float;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            camera.GetParameterPeriodicFlushEnabled(device, category, parameter, out int flushEnabled);

            var cmd = new CameraControlGetCommand
            {
                Input                = (VideoSource)device,
                Category             = category,
                Parameter            = parameter,
                Type                 = newType,
                PeriodicFlushEnabled = flushEnabled != 0,
            };

            switch (cmd.Type)
            {
            case CameraControlDataType.Bool:
            {
                uint count2 = count;
                camera.GetFlags(device, category, parameter, ref count2, out int values);
                int[] intVals   = Randomiser.ConvertSdkArray(count2, ref values);
                var   sbyteVals = new sbyte[count2];
                Buffer.BlockCopy(intVals, 0, sbyteVals, 0, (int)count2);
                cmd.BoolData = sbyteVals.Select(v => v != 0).ToArray();
                break;
            }

            case CameraControlDataType.SInt8:
            {
                uint count2 = count;
                camera.GetInt8s(device, category, parameter, ref count2, out sbyte values);
                cmd.IntData = Randomiser.ConvertSdkArray(count2, ref values).Select(v => (int)v).ToArray();
                break;
            }

            case CameraControlDataType.SInt16:
            {
                uint count2 = count;
                camera.GetInt16s(device, category, parameter, ref count2, out short values);
                cmd.IntData = Randomiser.ConvertSdkArray(count2, ref values).Select(v => (int)v).ToArray();
                break;
            }

            case CameraControlDataType.SInt32:
            {
                uint count2 = count;
                camera.GetInt32s(device, category, parameter, ref count2, out int values);
                cmd.IntData = Randomiser.ConvertSdkArray(count2, ref values);
                break;
            }

            case CameraControlDataType.SInt64:
            {
                uint count2 = count;
                camera.GetInt64s(device, category, parameter, ref count2, out long values);
                cmd.LongData = Randomiser.ConvertSdkArray(count2, ref values);
                break;
            }

            case CameraControlDataType.String:
            {
                camera.GetString(device, category, parameter, out string value);
                cmd.StringData = value;
                break;
            }

            case CameraControlDataType.Float:
            {
                uint count2 = count;
                camera.GetFloats(device, category, parameter, ref count2, out double values);
                cmd.FloatData = Randomiser.ConvertSdkArray(count2, ref values);
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(cmd);
        }