예제 #1
0
        public bool Do(VirtualFFBPacket Packet)
        {
            if (this.Packets.Count > 60)
            {
                this.PacketCleaning();
            }
            if (this.Effects.Count > 256)
            {
                this.EffectCleaning();
            }
            bool flag = true;

            if (//!this.UpdateBaseParams(Packet) &&
                !this.CreateBaseParams(Packet) &&
                //!this.UpdateTypeSpecificParams(Packet) &&
                //!this.UpdateEnvelopeParams(Packet) &&
                !this.EffectPlayback(Packet) &&
                !this.GainControl(Packet) &&
                !this.DeviceControl(Packet) &&
                !this.MiscControl(Packet))
            {
                flag = false;
            }
            this.Packets.Add(Packet);
            if (flag)
            {
                this.Effects.Sort(new Comparison <VirtualFFBEffect>(VirtualFFBState.EffectComparison_UpdateDateTime));
                return(true);
            }
            return(false);
        }
예제 #2
0
 public static void FFBPacketCallback(IntPtr data, object userData)
 {
     if (data != IntPtr.Zero)
     {
         Task.Run(() => {
             VirtualFFBPacket packet = ProcessFFBPacket(data, userData);
             packets.Enqueue(packet, packet.GetPriority());
         });
     }
 }
예제 #3
0
 private bool EffectDispose(VirtualFFBPacket Packet, VirtualFFBEffect Effect)
 {
     if (Packet.BlockIndex == Effect.Index)
     {
         Effect.Dispose();
         Effect.Packet = Packet;
         return(true);
     }
     return(false);
 }
예제 #4
0
 private bool GainControl(VirtualFFBPacket Packet)
 {
     if (Packet._FFBPType == FFBPType.PT_GAINREP)
     {
         this.Gain      = (int)Packet.Gain * 10000 / 255;
         Packet.Handled = true;
         return(true);
     }
     return(false);
 }
예제 #5
0
        private bool EffectPlayback(VirtualFFBPacket Packet, VirtualFFBEffect Effect)
        {
            if (Packet._FFBPType == FFBPType.PT_EFOPREP &&
                (int)Packet.FFB_EFF_OP.EffectBlockIndex == Effect.Index &&
                Effect.Status != EffectStatus.None &&
                Effect.Parameters.TriggerButton == -1)
            {
                Effect.UpdateStatus();
                switch (Packet.FFB_EFF_OP.EffectOp)
                {
                case FFBOP.EFF_START:
                    if (Effect.Status != EffectStatus.Playing)
                    {
                        Effect.LoopCount = (int)Packet.FFB_EFF_OP.LoopCount;
                        Effect.Solo      = false;
                        this.StartEffect(Effect);
                        Effect.Packet  = Packet;
                        Packet.Handled = true;
                        return(true);
                    }
                    break;

                case FFBOP.EFF_SOLO:
                    if (Effect.Status != EffectStatus.Playing)
                    {
                        for (int i = 0; i < this.Effects.Count; i++)
                        {
                            if (this.Effects[i] != Effect)
                            {
                                this.StopEffect(this.Effects[i]);
                                this.Effects[i].Packet = Packet;
                            }
                        }
                        Effect.LoopCount = (int)Packet.FFB_EFF_OP.LoopCount;
                        Effect.Solo      = true;
                        this.StartEffect(Effect);
                        Effect.Packet  = Packet;
                        Packet.Handled = true;
                        return(true);
                    }
                    break;

                case FFBOP.EFF_STOP:
                    if (Effect.Status == EffectStatus.Playing)
                    {
                        this.StopEffect(Effect);
                        Effect.Packet  = Packet;
                        Packet.Handled = true;
                        return(true);
                    }
                    break;
                }
            }
            return(false);
        }
예제 #6
0
        private bool DeviceControl(VirtualFFBPacket Packet)
        {
            if (Packet._FFBPType == FFBPType.PT_CTRLREP)
            {
                switch (Packet.FFB_CTRL)
                {
                case FFB_CTRL.CTRL_ENACT:
                    this.EnabledActuators = true;
                    break;

                case FFB_CTRL.CTRL_DISACT:
                    this.EnabledActuators = false;
                    break;

                case FFB_CTRL.CTRL_STOPALL:
                    for (int i = 0; i < this.Effects.Count; i++)
                    {
                        if (this.Effects[i].Status == EffectStatus.Playing && this.Effects[i].Parameters.TriggerButton == -1)
                        {
                            this.Effects[i].Packet = Packet;
                            this.StopEffect(this.Effects[i]);
                        }
                    }
                    this.DevicePause = false;
                    break;

                case FFB_CTRL.CTRL_DEVRST:
                    for (int j = 0; j < this.Effects.Count; j++)
                    {
                        if (this.Effects[j].Status == EffectStatus.Playing && this.Effects[j].Parameters.TriggerButton == -1)
                        {
                            this.Effects[j].Packet = Packet;
                            this.StopEffect(this.Effects[j]);
                        }
                    }
                    this.EnabledActuators = false;
                    this.Effects.Clear();
                    this.DevicePause      = false;
                    this.EnabledActuators = true;
                    break;

                case FFB_CTRL.CTRL_DEVPAUSE:
                    this.DevicePause = true;
                    break;

                case FFB_CTRL.CTRL_DEVCONT:
                    this.DevicePause = false;
                    break;
                }
                Packet.Handled = true;
                return(true);
            }
            return(false);
        }
예제 #7
0
        private bool MiscControl(VirtualFFBPacket Packet)
        {
            bool flag = false;

            switch (Packet._FFBPType)
            {
            case FFBPType.PT_BLKFRREP:
                flag = this.EffectDispose(Packet);
                break;
            }
            Packet.Handled = flag;
            return(flag);
        }
예제 #8
0
        private bool EffectPlayback(VirtualFFBPacket Packet)
        {
            if (this.DevicePause)
            {
                return(false);
            }
            bool result = false;

            for (int i = this.Effects.Count - 1; i >= 0; i--)
            {
                if (this.EffectPlayback(Packet, this.Effects[i]))
                {
                    result = true;
                    break;
                }
            }
            return(result);
        }
예제 #9
0
        private bool CreateBaseParams(VirtualFFBPacket Packet)
        {
            if (Packet._FFBPType != FFBPType.PT_EFFREP)
            {
                return(false);
            }
            if (this.DevicePause)
            {
                return(false);
            }
            EffectParametersEx baseEffectParameters = GetBaseEffectParameters(Packet.FFB_EFF_REPORT);
            VirtualFFBEffect   vJoyFFBEffect        = new VirtualFFBEffect();

            vJoyFFBEffect.Parameters = baseEffectParameters;
            vJoyFFBEffect.Index      = Packet.BlockIndex;
            int num = 0;

            for (int i = this.Packets.Count - 1; i >= 0; i--)
            {
                TimeSpan timeSpan = vJoyFFBEffect.CreationTime - this.Packets[i].CreationTime;
                if (this.Packets[i]._FFBPType == FFBPType.PT_EFFREP || timeSpan.TotalSeconds > 5.0)
                {
                    num = i;
                    break;
                }
            }
            bool flag = false;

            //for (int j = num; j < this.Packets.Count; j++) {
            //this.UpdateEnvelopeParams(this.Packets[j], vJoyFFBEffect);
            //if (this.UpdateTypeSpecificParams(this.Packets[j], vJoyFFBEffect)) {
            //    flag = true;
            //}
            //}
            if (flag)
            {
                vJoyFFBEffect.Status = EffectStatus.Idle;
            }
            vJoyFFBEffect.Packet = Packet;
            this.Effects.Add(vJoyFFBEffect);
            Packet.Handled = true;
            return(true);
        }
예제 #10
0
        public VirtualFFBEffect()
        {
            DateTime now = DateTime.Now;

            this.CreationTime   = now;
            this.UpdateTime     = now;
            this.BaseUpdateTime = now;
            this.StartTime      = DateTime.MinValue;
            this.StopTime       = DateTime.MinValue;
            this.Status         = EffectStatus.None;
            this.Downloaded     = false;
            this.Parameters     = new EffectParametersEx();
            this.ConditionX     = false;
            this.ConditionY     = false;
            this.Solo           = false;
            this.LoopCount      = 1;
            this.Packet         = null;

            this.Index = 0;
        }
예제 #11
0
 public static void FFBProcessingThread()
 {
     try {
         logger.Info("Starting FFBProcThread");
         while (true)
         {
             while (packets.Count > 0)
             {
                 VirtualFFBPacket packet = packets.Dequeue();
                 handlers[packet.ID]?.Invoke(packet);
                 //FFBDataReceived?.Invoke(packets.Dequeue());
                 //Thread.Sleep(1);
             }
             Thread.Sleep(100);
             //newDataEvent.WaitOne();
         }
     } catch (ThreadAbortException) {
         logger.Info("Stopping FFBProcThread");
     } catch (Exception ex) {
         logger.Warn($"FFBProcThread WTF {ex}");
     } finally {
         packets.Clear();
     }
 }
예제 #12
0
        public static VirtualFFBPacket ProcessFFBPacket(IntPtr data, object userData)
        {
            VirtualFFBPacket FFBPacket = new VirtualFFBPacket();

            if (joystick.Ffb_h_Type(data, ref FFBPacket._FFBPType) == ERROR_SUCCESS)
            {
                joystick.Ffb_h_DeviceID(data, ref FFBPacket.ID);
                switch (FFBPacket._FFBPType)
                {
                case FFBPType.PT_EFFREP:     // Effect Report (also named EFFECT_CONST)
                    if (joystick.Ffb_h_Eff_Report(data, ref FFBPacket.FFB_EFF_REPORT) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = FFBPacket.FFB_EFF_REPORT.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Effect Report");
                        logger.Trace(FFBPacket.GenerateEffectInfo());
                    }
                    break;

                case FFBPType.PT_ENVREP:     // Envelope Report
                    if (joystick.Ffb_h_Eff_Envlp(data, ref FFBPacket.FFB_EFF_ENVLP) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_ENVLP.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Envelope Report");
                    }
                    break;

                case FFBPType.PT_CONDREP:     // Condition Report !!
                    if (joystick.Ffb_h_Eff_Cond(data, ref FFBPacket.FFB_EFF_COND) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_COND.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Condition Report");
                        StringBuilder dat = new StringBuilder();
                        dat.AppendFormat($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Condition Report\n");
                        dat.AppendFormat($"\t EBI={FFBPacket.FFB_EFF_COND.EffectBlockIndex}\n");
                        dat.AppendFormat($"\t Center={FFBPacket.FFB_EFF_COND.CenterPointOffset}\n");
                        dat.AppendFormat($"\t DeadBand={FFBPacket.FFB_EFF_COND.DeadBand}\n");
                        dat.AppendFormat($"\t isY={FFBPacket.FFB_EFF_COND.isY}\n");
                        dat.AppendFormat($"\t NegCoeff={FFBPacket.FFB_EFF_COND.NegCoeff}\n");
                        dat.AppendFormat($"\t NegSatur={FFBPacket.FFB_EFF_COND.NegSatur}\n");
                        dat.AppendFormat($"\t PosCoeff={FFBPacket.FFB_EFF_COND.PosCoeff}\n");
                        dat.AppendFormat($"\t PosSatur={FFBPacket.FFB_EFF_COND.PosSatur}");
                        logger.Trace(dat);
                    }
                    break;

                case FFBPType.PT_PRIDREP:     // Periodic Report
                    if (joystick.Ffb_h_Eff_Period(data, ref FFBPacket.FFB_EFF_PERIOD) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_PERIOD.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Periodic Report");
                        StringBuilder dat = new StringBuilder();
                        dat.AppendFormat($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Periodic Report\n");
                        dat.AppendFormat($"\t EBI={FFBPacket.FFB_EFF_PERIOD.EffectBlockIndex}\n");
                        dat.AppendFormat($"\t Magnitude={FFBPacket.FFB_EFF_PERIOD.Magnitude}\n");
                        dat.AppendFormat($"\t Offset={FFBPacket.FFB_EFF_PERIOD.Offset}\n");
                        dat.AppendFormat($"\t Period={FFBPacket.FFB_EFF_PERIOD.Period}\n");
                        dat.AppendFormat($"\t Phase={FFBPacket.FFB_EFF_PERIOD.Phase}");
                        logger.Trace(dat);
                    }
                    break;

                case FFBPType.PT_CONSTREP:     // Constant Force Report
                    if (joystick.Ffb_h_Eff_Constant(data, ref FFBPacket.FFB_EFF_CONSTANT) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_CONSTANT.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Constant Force Report, magnitude={FFBPacket.FFB_EFF_CONSTANT.Magnitude}");
                    }
                    break;

                case FFBPType.PT_RAMPREP:     // Ramp Force Report
                    if (joystick.Ffb_h_Eff_Ramp(data, ref FFBPacket.FFB_EFF_RAMP) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_RAMP.EffectBlockIndex;
                        logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Ramp Force Report");
                        StringBuilder dat = new StringBuilder();
                        dat.AppendFormat($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Ramp Force Report\n");
                        dat.AppendFormat($"\t EBI={FFBPacket.FFB_EFF_RAMP.EffectBlockIndex}\n");
                        dat.AppendFormat($"\t Start={FFBPacket.FFB_EFF_RAMP.Start}\n");
                        dat.AppendFormat($"\t End={FFBPacket.FFB_EFF_RAMP.End}\n");
                        logger.Trace(dat);
                    }
                    break;

                case FFBPType.PT_CSTMREP:     // Custom Force Data Report
                    logger.Debug($"Custom Force Data Report");
                    break;

                case FFBPType.PT_SMPLREP:     // Download Force Sample
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Download Force Sample");
                    break;

                case FFBPType.PT_EFOPREP:     // Effect Operation Report
                    if (joystick.Ffb_h_EffOp(data, ref FFBPacket.FFB_EFF_OP) == ERROR_SUCCESS)
                    {
                        FFBPacket.BlockIndex = (uint)FFBPacket.FFB_EFF_OP.EffectBlockIndex;
                        logger.Trace($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Effect Operation Report loop={FFBPacket.FFB_EFF_OP.LoopCount} action={FFBPacket.FFB_EFF_OP.EffectOp}");
                    }
                    break;

                case FFBPType.PT_BLKFRREP:     // PID Block Free Report
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] PID Block Free Report");
                    break;

                case FFBPType.PT_CTRLREP:     // PID Device Control
                    joystick.Ffb_h_DevCtrl(data, ref FFBPacket.FFB_CTRL);
                    logger.Debug($"[{FFBPacket.ID}][_] PID Device Control {FFBPacket.FFB_CTRL}");
                    break;

                case FFBPType.PT_GAINREP:     // Device Gain Report
                    joystick.Ffb_h_DevGain(data, ref FFBPacket.Gain);
                    logger.Debug($"[{FFBPacket.ID}][_] Device Gain Report={FFBPacket.Gain}");
                    break;

                case FFBPType.PT_SETCREP:     // Set Custom Force Report
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Set Custom Force Report");
                    break;

                case FFBPType.PT_NEWEFREP:     // Create New Effect Report !!
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    joystick.Ffb_h_CreateNewEffect(data, ref FFBPacket.FFBENextType, ref FFBPacket.NextBlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Create New Effect Report, next={FFBPacket.FFBENextType}[nextEBI={FFBPacket.NextBlockIndex}]");
                    break;

                case FFBPType.PT_BLKLDREP:     // Block Load Report
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] Block Load Report");
                    break;

                case FFBPType.PT_POOLREP:     // PID Pool Report
                    joystick.Ffb_h_EBI(data, ref FFBPacket.BlockIndex);
                    logger.Debug($"[{FFBPacket.ID}][EBI={FFBPacket.BlockIndex}] PID Pool Report");
                    break;
                }
                // FFBDataReceived?.Invoke(FFBPacket);
                return(FFBPacket);
            }
            return(null);
        }
예제 #13
0
        public void InitFromFFBPacket(VirtualFFBPacket packet)
        {
            if (packet._FFBPType != FFBPType.PT_NEWEFREP && packet._FFBPType != FFBPType.PT_EFFREP)
            {
                return;
            }
            if (this.Parameters.Index == 10000)
            {
                FFBEType type;
                if (packet._FFBPType == FFBPType.PT_NEWEFREP)
                {
                    type = packet.FFBENextType;
                }
                else
                {
                    type = packet.FFB_EFF_REPORT.EffectType;
                }
                this.Parameters.Type  = VirtualController.virtualEffectGuidMap[type];
                this.Parameters.Index = packet.BlockIndex;
                switch (type)
                {
                case FFBEType.ET_CONST: {
                    if (this.Parameters.Parameters == null)
                    {
                        this.Parameters.Parameters = new ConstantForce()
                        {
                            Magnitude = 10000,
                        }
                    }
                    ;
                    this.Parameters.FType = ForceType.Constant;
                    break;
                }

                case FFBEType.ET_RAMP: {
                    if (this.Parameters.Parameters == null)
                    {
                        this.Parameters.Parameters = new RampForce()
                        {
                            Start = -10000,
                            End   = 10000,
                        }
                    }
                    ;
                    this.Parameters.FType = ForceType.Ramp;
                    break;
                }

                case FFBEType.ET_SINE:
                case FFBEType.ET_SQR:
                case FFBEType.ET_STDN:
                case FFBEType.ET_STUP:
                case FFBEType.ET_TRNGL: {
                    if (this.Parameters.Parameters == null)
                    {
                        this.Parameters.Parameters = new PeriodicForce()
                        {
                            Magnitude = 10000,
                            Offset    = 0,
                            Period    = 500000,
                            Phase     = 0
                        }
                    }
                    ;
                    this.Parameters.FType = ForceType.Periodic;
                    break;
                }

                case FFBEType.ET_DMPR:
                case FFBEType.ET_FRCTN:
                case FFBEType.ET_INRT:
                case FFBEType.ET_SPRNG: {
                    if (this.Parameters.Parameters == null)
                    {
                        this.Parameters.Parameters = new ConditionSet();
                        this.Parameters.Parameters.As <ConditionSet>().Conditions    = new Condition[1];
                        this.Parameters.Parameters.As <ConditionSet>().Conditions[0] = new Condition()
                        {
                            DeadBand            = 0,
                            NegativeCoefficient = 10000,
                            NegativeSaturation  = 10000,
                            Offset = 0,
                            PositiveCoefficient = 10000,
                            PositiveSaturation  = 10000
                        };
                    }
                    this.Parameters.FType = ForceType.Condition;
                    break;
                }

                case FFBEType.ET_CSTM: { break; }
                }

                Parameters.Duration              = -1;
                Parameters.Gain                  = 10000;
                Parameters.SamplePeriod          = 0;
                Parameters.StartDelay            = 0;
                Parameters.TriggerButton         = -1;
                Parameters.TriggerRepeatInterval = 0;
                Parameters.Flags                 = (EffectFlags.ObjectIds | EffectFlags.Cartesian);
                Parameters.Directions            = new int[1] {
                    1
                };
            }
        }
예제 #14
0
        public void UpdateFromFFBPacket(VirtualFFBPacket packet)
        {
            if (packet._FFBPType != FFBPType.PT_EFFREP)
            {
                return;
            }

            if (packet.FFB_EFF_REPORT.Duration == 65535)
            {
                Parameters.Duration = -1;
            }
            else
            {
                Parameters.Duration = (int)(packet.FFB_EFF_REPORT.Duration * 1000);
            }
            Parameters.Gain         = (int)(packet.FFB_EFF_REPORT.Gain * (10000 / 255.0));
            Parameters.SamplePeriod = (int)(packet.FFB_EFF_REPORT.SamplePrd * 1000);
            Parameters.StartDelay   = 0;
            if (packet.FFB_EFF_REPORT.TrigerBtn == 255)
            {
                Parameters.TriggerButton = -1;
            }
            else
            {
                Parameters.TriggerButton = (int)packet.FFB_EFF_REPORT.TrigerBtn;
            }
            Parameters.TriggerRepeatInterval = (int)(packet.FFB_EFF_REPORT.TrigerRpt * 1000);
            Parameters.Flags = (EffectFlags.ObjectIds | EffectFlags.Cartesian);

            /*
             * So there a very strange moment: vjoy always sends packet.FFB_EFF_REPORT.Polar is true.
             * So, a solution also very strange and hacky.
             */

            if (packet.FFB_EFF_REPORT.Polar)
            {
                Parameters.Directions = new int[1];
                // 1/0 + 0 = 8191
                // -1  + 0 = 24575
                // 0   + 1 = 16383
                // 0   +-1 = 0
                //
                switch (packet.FFB_EFF_REPORT.Direction)
                {
                case 0: {
                    Program.logger.Fatal($"RECIVED ZERO PACKET _START");
                    Program.logger.Fatal(packet.GenerateEffectInfo());
                    Program.logger.Fatal($"RECIVED ZERO PACKET _END");
                    Parameters.Directions[0] = 0;
                    break;
                }

                case 8191: {
                    Parameters.Directions[0] = 1;
                    break;
                }

                case 24575: {
                    Parameters.Directions[0] = -1;
                    break;
                }

                default: {
                    Parameters.Directions[0] = 0;
                    break;
                }
                }
            }
            else
            {
                Parameters.Directions    = new int[2];
                Parameters.Directions[0] = (int)packet.FFB_EFF_REPORT.DirX;
                Parameters.Directions[1] = (int)packet.FFB_EFF_REPORT.DirY;

                Program.logger.Fatal($"RECIVED NOT POLAR PACKET _START");
                Program.logger.Fatal(packet.GenerateEffectInfo());
                Program.logger.Fatal($"RECIVED NOT POLAR PACKET _END");
            }
            //effectParameters.AxisSettings = new AxisSettings(2);
            //Parameters.Directions = new int[2];

            /*int num = 0;
             * int num2 = 0;
             * if (packet.FFB_EFF_REPORT.Polar) {
             *  Utils.GetDICartesianXY((int)packet.FFB_EFF_REPORT.DirX, ref num, ref num2);
             * } else {
             *  num = (int)packet.FFB_EFF_REPORT.DirX;
             *  num2 = (int)packet.FFB_EFF_REPORT.DirY;
             * }
             * Parameters.Directions[0] = num;
             * Parameters.Directions[1] = num2; */
        }