private void FireStateChangedEvents(ControllerState controller)
 {
     AxisStateChanged?.Invoke(Axis.AimingX, controller.AimingX);
     AxisStateChanged?.Invoke(Axis.AimingY, controller.AimingY);
     AxisStateChanged?.Invoke(Axis.BrakePedal, controller.BrakePedal);
     ButtonStateChanged?.Invoke(Button.ToggleBufferMaterial, controller.BufferMaterial != 0);
     ButtonStateChanged?.Invoke(Button.Chaff, controller.Chaff != 0);
     ButtonStateChanged?.Invoke(Button.CockpitHatch, controller.CockpitHatch != 0);
     ButtonStateChanged?.Invoke(Button.Comm1, controller.Comm1 != 0);
     ButtonStateChanged?.Invoke(Button.Comm2, controller.Comm2 != 0);
     ButtonStateChanged?.Invoke(Button.Comm3, controller.Comm3 != 0);
     ButtonStateChanged?.Invoke(Button.Comm4, controller.Comm4 != 0);
     ButtonStateChanged?.Invoke(Button.Comm5, controller.Comm5 != 0);
     ButtonStateChanged?.Invoke(Button.Eject, controller.Eject != 0);
     ButtonStateChanged?.Invoke(Button.Extinguisher, controller.Extinguisher != 0);
     ButtonStateChanged?.Invoke(Button.FunctionF1, controller.F1 != 0);
     ButtonStateChanged?.Invoke(Button.FunctionF2, controller.F2 != 0);
     ButtonStateChanged?.Invoke(Button.FunctionF3, controller.F3 != 0);
     ButtonStateChanged?.Invoke(Button.ToggleFilterControl, controller.FilterControlSystem != 0);
     ButtonStateChanged?.Invoke(Button.FunctionFSS, controller.ForecastShootingSystem != 0);
     ButtonStateChanged?.Invoke(Button.ToggleFuelFlowRate, controller.FuelFlowRate != 0);
     AxisStateChanged?.Invoke(Axis.Throttle, controller.GasPedal);
     GearChanged?.Invoke(controller.Gear);
     ButtonStateChanged?.Invoke(Button.Ignition, controller.Ignition != 0);
     ButtonStateChanged?.Invoke(Button.FunctionLineColorChange, controller.LineColorChange != 0);
     ButtonStateChanged?.Invoke(Button.RightJoyLockOn, controller.LockOn != 0);
     ButtonStateChanged?.Invoke(Button.WeaponConMagazine, controller.MagazineChange != 0);
     ButtonStateChanged?.Invoke(Button.MainMonZoomIn, controller.MainMonitorZoomIn != 0);
     ButtonStateChanged?.Invoke(Button.MainMonZoomOut, controller.MainMonitorZoomOut != 0);
     ButtonStateChanged?.Invoke(Button.WeaponConMain, controller.MainWeaponControl != 0);
     ButtonStateChanged?.Invoke(Button.RightJoyMainWeapon, controller.MainWeaponFire != 0);
     ButtonStateChanged?.Invoke(Button.FunctionManipulator, controller.Manipulator != 0);
     ButtonStateChanged?.Invoke(Button.MultiMonMapZoomInOut, controller.MultiMonitorMapZoom != 0);
     ButtonStateChanged?.Invoke(Button.MultiMonModeSelect, controller.MultiMonitorModeSelect != 0);
     ButtonStateChanged?.Invoke(Button.MultiMonOpenClose, controller.MultiMonitorOpenClose != 0);
     ButtonStateChanged?.Invoke(Button.FunctionNightScope, controller.NightScope != 0);
     ButtonStateChanged?.Invoke(Button.FunctionOverride, controller.Override != 0);
     ButtonStateChanged?.Invoke(Button.ToggleOxygenSupply, controller.OxygenSupplySystem != 0);
     AxisStateChanged?.Invoke(Axis.Rotation, controller.Rotation);
     ButtonStateChanged?.Invoke(Button.LeftJoySightChange, controller.SightChange != 0);
     AxisStateChanged?.Invoke(Axis.SightChangeX, controller.SightChangeX);
     AxisStateChanged?.Invoke(Axis.SightChangeY, controller.SightChangeY);
     ButtonStateChanged?.Invoke(Button.Start, controller.Start != 0);
     AxisStateChanged?.Invoke(Axis.StrafePedal, controller.StrafePedal);
     ButtonStateChanged?.Invoke(Button.SubMonitorModeSelect, controller.SubMonitorModeSelect != 0);
     ButtonStateChanged?.Invoke(Button.WeaponConSub, controller.SubWeaponControl != 0);
     ButtonStateChanged?.Invoke(Button.RightJoyFire, controller.SubWeaponFire != 0);
     ButtonStateChanged?.Invoke(Button.FunctionTankDetach, controller.TankDetach != 0);
     TunerStateChanged?.Invoke(controller.TunerDial);
     ButtonStateChanged?.Invoke(Button.ToggleVTLocation, controller.VTLocationMeasurement != 0);
     ButtonStateChanged?.Invoke(Button.Washing, controller.Washing != 0);
 }
        private void listeningThreadFunc()
        {
            MessageHeader header = MessageHeader.NoMessage;
            Button        button;
            Axis          axis;
            Gear          gear;
            byte          tuner;
            byte          bstate;
            float         fstate;

            byte[]          dword      = { 0, 0, 0, 0 };
            ControllerState controller = new ControllerState();

            byte[] controllerStateBytes = new byte[Marshal.SizeOf(controller)];
            IntPtr ptr = IntPtr.Zero;

            var server = this.server; // Create a copy

            do
            {
                try
                {
                    header = (MessageHeader)server.ReadByte();
                    switch (header)
                    {
                    case MessageHeader.ControllerState:
                        if (server.Read(controllerStateBytes, 0, controllerStateBytes.Length) == controllerStateBytes.Length)
                        {
                            var handle = GCHandle.Alloc(controllerStateBytes, GCHandleType.Pinned);
                            controller = (ControllerState)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ControllerState));
                            handle.Free();
                            FireStateChangedEvents(controller);
                        }
                        break;

                    case MessageHeader.ButtonChanged:
                        button = (Button)server.ReadByte();
                        bstate = (byte)server.ReadByte();
                        ButtonStateChanged?.Invoke(button, bstate != 0);
                        break;

                    case MessageHeader.AxisChanged:
                        axis = (Axis)server.ReadByte();
                        server.Read(dword, 0, 4);
                        fstate = BitConverter.ToSingle(dword, 0);
                        AxisStateChanged?.Invoke(axis, fstate);
                        break;

                    case MessageHeader.GearChanged:
                        gear            = (Gear)server.ReadByte();
                        controller.Gear = gear;
                        GearChanged?.Invoke(gear);
                        break;

                    case MessageHeader.TunerChanged:
                        tuner = (byte)server.ReadByte();
                        controller.TunerDial = tuner;
                        TunerStateChanged?.Invoke(tuner);
                        break;
                    }
                }
                catch
                {
                }
            } while (server.IsConnected);

            lock (this)
            {
                if (server != null)
                {
                    server.Dispose();
                    server = null;
                    Connect();
                }
            }
        }