diff --git a/plugins/onepad/GamePad.h b/plugins/onepad/GamePad.h index 1d400715fb..10e2dd9766 100644 --- a/plugins/onepad/GamePad.h +++ b/plugins/onepad/GamePad.h @@ -42,7 +42,7 @@ class GamePad * Causes devices to rumble * Rumble will differ according to type which is either 0(small motor) or 1(big motor) **/ - virtual void Rumble(int type){return;} + virtual void Rumble(int type,int pad){return;} virtual bool Init(int id){return false;} // opens a handle and gets information diff --git a/plugins/onepad/Linux/dialog.cpp b/plugins/onepad/Linux/dialog.cpp index 03c68fbfcc..2a3e3f10d3 100644 --- a/plugins/onepad/Linux/dialog.cpp +++ b/plugins/onepad/Linux/dialog.cpp @@ -393,7 +393,11 @@ void on_toggle_option(GtkToggleButton *togglebutton, gpointer user_data) dialog_checkbox *checkbox = (dialog_checkbox*)user_data; if (gtk_toggle_button_get_active(togglebutton)) + { conf->packed_options |= checkbox->mask; + if(checkbox->mask == PADOPTION_FORCEFEEDBACK && (conf->get_joyid(current_pad)< s_vgamePad.size())) + s_vgamePad[conf->get_joyid(current_pad)]->TestForce(); + } else conf->packed_options &= ~checkbox->mask; } diff --git a/plugins/onepad/SDL/joystick.cpp b/plugins/onepad/SDL/joystick.cpp index 6cf3b36317..7d2acfdb6f 100644 --- a/plugins/onepad/SDL/joystick.cpp +++ b/plugins/onepad/SDL/joystick.cpp @@ -50,10 +50,7 @@ void JoystickInfo::EnumerateJoysticks(vector& vjoysticks) #if SDL_MAJOR_VERSION >= 2 // Tell SDL to catch event even if the windows isn't focussed SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - // SDL in 3rdparty wrap X11 call. In order to get x11 symbols loaded - // video must be loaded too. - // Example of X11 symbol are XAutoRepeatOn/XAutoRepeatOff - if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_VIDEO|SDL_INIT_HAPTIC|SDL_INIT_GAMECONTROLLER|SDL_INIT_EVENTS) < 0) return; + if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_HAPTIC|SDL_INIT_EVENTS) < 0) return; #else if (SDL_Init(SDL_INIT_JOYSTICK) < 0) return; #endif @@ -79,72 +76,68 @@ void JoystickInfo::EnumerateJoysticks(vector& vjoysticks) } } -void JoystickInfo::InitHapticEffect() +void JoystickInfo::GenerateDefaultEffect() { -#if SDL_MAJOR_VERSION >= 2 - if (haptic == NULL) return; - -#if 0 - additional field of the effect - /* Trigger */ - Uint16 button; /**< Button that triggers the effect. */ - Uint16 interval; /**< How soon it can be triggered again after button. */ - - // periodic parameter - Sint16 offset; /**< Mean value of the wave. */ - Uint16 phase; /**< Horizontal shift given by hundredth of a cycle. */ -#endif - - /*******************************************************************/ - /* Effect big & small */ - /*******************************************************************/ - for (int new_effect = 0; new_effect < 2 ; new_effect++) { - - // Direction of the effect SDL_HapticDirection - haptic_effect_data[new_effect].periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates - haptic_effect_data[new_effect].periodic.direction.dir[0] = 18000; // Force comes from south - - // periodic parameter - haptic_effect_data[new_effect].periodic.period = 20; // 20 ms - haptic_effect_data[new_effect].periodic.magnitude = 2000; // 2000/32767 strength - - // Replay - haptic_effect_data[new_effect].periodic.length = 60; // 60 ms long - haptic_effect_data[new_effect].periodic.delay = 0; // start 0 second after the upload - - // enveloppe - haptic_effect_data[new_effect].periodic.attack_length = 5;// Takes 5 ms to get max strength - haptic_effect_data[new_effect].periodic.attack_level = 0; // start at 0 - haptic_effect_data[new_effect].periodic.fade_length = 5; // Takes 5 ms to fade away - haptic_effect_data[new_effect].periodic.fade_level = 0; // finish at 0 + for(int i=0;iget_ff_intensity()); // Effect at maximum instensity + effect.periodic.offset = 0; + effect.periodic.phase = 18000; + effect.periodic.length = 125; // 125ms feels quite near to original + effect.periodic.delay = 0; + effect.periodic.attack_length = 0; + effects[i] = effect; } - - /*******************************************************************/ - /* Effect small */ - /*******************************************************************/ - haptic_effect_data[0].type = SDL_HAPTIC_LEFTRIGHT; - - /*******************************************************************/ - /* Effect big */ - /*******************************************************************/ - haptic_effect_data[1].type = SDL_HAPTIC_TRIANGLE; - - /*******************************************************************/ - /* Upload effect to the device */ - /*******************************************************************/ - for (int i = 0 ; i < 2 ; i++) - haptic_effect_id[i] = SDL_HapticNewEffect(haptic, &haptic_effect_data[i]); -#endif } -void JoystickInfo::Rumble(int type) +void JoystickInfo::Rumble(int type, int pad) { if (type > 1) return; if ( !(conf->pad_options[pad].forcefeedback) ) return; #if SDL_MAJOR_VERSION >= 2 if (haptic == NULL) return; - return; + + if(first) + {// If done multiple times, device memory will be filled + first = 0; + GenerateDefaultEffect(); + /** Sine and triangle are quite probably the best, don't change that lightly and if you do + * keep effects ordered by type + **/ + /** Effect for small motor **/ + /** Sine seems to be the only effect making little motor from DS3/4 react + * Intensity has pretty much no effect either(which is coherent with what is explain in hid_sony driver + **/ + effects[0].type = SDL_HAPTIC_SINE; + effects_id[0] = SDL_HapticNewEffect(haptic, &effects[0]); + if(effects_id[0] < 0) + { + fprintf(stderr,"ERROR: Effect is not uploaded! %s, id is %d\n",SDL_GetError(),effects_id[0]); + } + + /** Effect for big motor **/ + effects[1].type = SDL_HAPTIC_TRIANGLE; + effects_id[1] = SDL_HapticNewEffect(haptic, &effects[1]); + if(effects_id[1] < 0) + { + fprintf(stderr,"ERROR: Effect is not uploaded! %s, id is %d\n",SDL_GetError(),effects_id[1]); + } + } + + int id; + id = effects_id[type]; + if(SDL_HapticRunEffect(haptic, id, 1) != 0) + { + fprintf(stderr,"ERROR: Effect is not working! %s, id is %d\n",SDL_GetError(),id); + } #endif } @@ -161,7 +154,9 @@ void JoystickInfo::Destroy() #endif #if SDL_MAJOR_VERSION >= 2 +#if SDL_MINOR_VERSION >= 4 // Version before 2.0.4 are bugged, JoystickClose crashes randomly if (joy) SDL_JoystickClose(joy); +#endif #else if (SDL_JoystickOpened(_id)) SDL_JoystickClose(joy); #endif @@ -212,8 +207,7 @@ bool JoystickInfo::Init(int id) PAD_LOG("Haptic devices not supported!\n"); } else { haptic = SDL_HapticOpenFromJoystick(joy); - // upload some default effect - InitHapticEffect(); + first = true; } } #endif @@ -233,7 +227,14 @@ void JoystickInfo::SaveState() } void JoystickInfo::TestForce() -{ +{ // This code just use standard rumble to check that SDL handles the pad correctly! --3kinox + if(haptic == NULL) return; // Otherwise, core dump! + SDL_HapticRumbleInit( haptic ); + // Make the haptic pad rumble 60% strength for half a second, shoudld be enough for user to see if it works or not + if( SDL_HapticRumblePlay( haptic, 0.60, 400 ) != 0) + { + fprintf(stderr,"ERROR: Rumble is not working! %s\n",SDL_GetError()); + } } bool JoystickInfo::PollButtons(u32 &pkey) diff --git a/plugins/onepad/SDL/joystick.h b/plugins/onepad/SDL/joystick.h index 1941c0b049..6ec6187d07 100644 --- a/plugins/onepad/SDL/joystick.h +++ b/plugins/onepad/SDL/joystick.h @@ -29,20 +29,19 @@ #include "GamePad.h" #include "onepad.h" #include "controller.h" - +#define NB_EFFECT 2 // Don't use more than two, ps2 only has one for big motor and one for small(like most systems) // holds all joystick info class JoystickInfo : GamePad { public: JoystickInfo() : devname(""), _id(-1), numbuttons(0), numaxes(0), numhats(0), deadzone(1500), pad(-1), joy(NULL) { - vbuttonstate.clear(); - vaxisstate.clear(); - vhatstate.clear(); + vbuttonstate.clear(); + vaxisstate.clear(); + vhatstate.clear(); #if SDL_MAJOR_VERSION >= 2 - haptic = NULL; - for (int i = 0 ; i < 2 ; i++) - haptic_effect_id[i] = -1; + haptic = NULL; + first = true; #endif } @@ -58,8 +57,7 @@ class JoystickInfo : GamePad // opens handles to all possible joysticks static void EnumerateJoysticks(vector& vjoysticks); - void InitHapticEffect(); - void Rumble(int type); + void Rumble(int type,int pad); bool Init(int id); // opens a handle and gets information @@ -146,6 +144,7 @@ class JoystickInfo : GamePad { return joy; } + void GenerateDefaultEffect(); string devname; // pretty device name int _id; int numbuttons, numaxes, numhats; @@ -157,7 +156,8 @@ class JoystickInfo : GamePad SDL_Joystick* joy; #if SDL_MAJOR_VERSION >= 2 SDL_Haptic* haptic; - SDL_HapticEffect haptic_effect_data[2]; - int haptic_effect_id[2]; + bool first; + SDL_HapticEffect effects[NB_EFFECT]; + int effects_id[NB_EFFECT]; #endif }; diff --git a/plugins/onepad/onepad.cpp b/plugins/onepad/onepad.cpp index f77bf5d48d..91d796ff39 100644 --- a/plugins/onepad/onepad.cpp +++ b/plugins/onepad/onepad.cpp @@ -300,7 +300,6 @@ EXPORT_C_(u32) PADquery() void PADsetMode(int pad, int mode) { padMode[pad] = mode; - // FIXME FEEDBACK padVib0[pad] = 0; padVib1[pad] = 0; padVibF[pad][0] = 0; @@ -413,7 +412,6 @@ u8 _PADpoll(u8 value) buf = stdpar[curPad]; - // FIXME FEEDBACK. Set effect here /* Small Motor */ vib_small = padVibF[curPad][0] ? 2000 : 0; // if ((padVibF[curPad][2] != vib_small) && (padVibC[curPad] >= 0)) @@ -422,7 +420,7 @@ u8 _PADpoll(u8 value) padVibF[curPad][2] = vib_small; // SetDeviceForceS (padVibC[curPad], vib_small); GamePad* gamePad = s_vgamePad[conf->get_joyid(curPad)]; - gamePad->Rumble(0); + gamePad->Rumble(0,curPad); } /* Big Motor */ @@ -433,7 +431,7 @@ u8 _PADpoll(u8 value) padVibF[curPad][3] = vib_big; // SetDeviceForceB (padVibC[curPad], vib_big); GamePad* gamePad = s_vgamePad[conf->get_joyid(curPad)]; - gamePad->Rumble(1); + gamePad->Rumble(1,curPad); } return padID[curPad]; @@ -493,7 +491,7 @@ u8 _PADpoll(u8 value) switch (curCmd) { case CMD_READ_DATA_AND_VIBRATE: - // FIXME FEEDBACK + if (curByte == padVib0[curPad]) padVibF[curPad][0] = value; if (curByte == padVib1[curPad]) @@ -559,7 +557,7 @@ u8 _PADpoll(u8 value) break; case CMD_VIBRATION_TOGGLE: - // FIXME FEEDBACK + if (curByte >= 2) { if (curByte == padVib0[curPad]) @@ -569,16 +567,10 @@ u8 _PADpoll(u8 value) if (value == 0x00) { padVib0[curPad] = curByte; - // FIXME: code from SSSXPAD I'm not sure we need this part - // if ((padID[curPad] & 0x0f) < (curByte - 1) / 2) - // padID[curPad] = (padID[curPad] & 0xf0) + (curByte - 1) / 2; } else if (value == 0x01) { padVib1[curPad] = curByte; - // FIXME: code from SSSXPAD I'm not sure we need this part - // if ((padID[curPad] & 0x0f) < (curByte - 1) / 2) - // padID[curPad] = (padID[curPad] & 0xf0) + (curByte - 1) / 2; } } break;