The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
Gamecontroller and Joystick events not working! (v2.0.3 &
blueshogun96


Joined: 12 Jul 2015
Posts: 4
Okay, first I want to say thanks to all the hard work everyone has put into SDL 2.0. I written a fairly complex and large engine and SDL helped make much of the portability prospects a reality. It's indeed a privilege to have such a great library available for use!

But right now, I really need to find out why gamecontroller and joystick events aren't being triggered. I don't know why this doesn't work, especially when the documentation tells me exactly how it's done. It appears to me that SDL events don't always work; I mean, I've had instances where NONE of the event types would be processesed for a few days, then suddenly start working again. I dunno, what the frell is going on?

This should be rather straight forward, but I guess not. This is the code I use to handle gamepads and such...

Code:
#include "KeGamepad.h"
#include <vector>


/* Gamepad handle */
class CKeGamepadHandle
{
public:
   CKeGamepadHandle() : game_controller(NULL), haptic(NULL), joystick_id(0), id(0), connected(No) {}
   ~CKeGamepadHandle()
   {
      if( haptic )
         SDL_HapticClose( haptic );

      SDL_GameControllerClose( game_controller );
   }

   SDL_GameController* game_controller;
   SDL_Haptic*         haptic;
   SDL_JoystickID      joystick_id;
   KeGamepadState      state;
   int               id;
   bool            connected;
};

/* Gamepad handles */
std::vector<CKeGamepadHandle> GamepadHandles;


/*
 * Name: KeInitializeGamepads
 * Desc: Initializes the gamepad API for the target platform.
 */
bool KeInitializeGamepads()
{
   int ret = 0;

   /* Initialize SDL2 gamepad API */
   ret = SDL_InitSubSystem( SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC );
   if( ret != 0 )
      DISPDBG( KE_ERROR, "An error has occured initializing SDL controller API!" );
   
   /* Enable joystick events */
   SDL_JoystickEventState( SDL_ENABLE );

   return ret;
}


/*
 * Name: KeUnintializeGamepads
 * Desc: Uninitializes the above.
 */
void KeUninitializeGamepads()
{
   /* Kill all open gamepad devices */
   GamepadHandles.empty();

   /* Uninitialize the gamepad API */
   SDL_QuitSubSystem( SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC );
}


/*
 * Name: KeOnGamepadAdded
 * Desc: Called when a gamepad has been added/attached.
 */
void KeOnGamepadAdded( int device_id )
{
   CKeGamepadHandle handle;

   /* Attempt to open this device */
   handle.game_controller = SDL_GameControllerOpen( device_id );

   /* Get the joystick instance ID */
   SDL_Joystick* j = SDL_GameControllerGetJoystick( handle.game_controller );
   handle.joystick_id = SDL_JoystickInstanceID(j);
   handle.connected = Yes;
   handle.id = device_id;

   ZeroMemory( &handle.state, sizeof( KeGamepadState ) );

   /* Is this a haptic device? */
   if( SDL_JoystickIsHaptic(j) )
   {
      handle.haptic = SDL_HapticOpenFromJoystick(j);

      /* Is this a rumble supported haptic feature? */
      if( SDL_HapticRumbleSupported( handle.haptic ) )
      {
         /* Can we initialize the rumble feature? */
         if( SDL_HapticRumbleInit( handle.haptic ) )
         {
            /* An error occurred */
            SDL_HapticClose( handle.haptic );
            handle.haptic = 0;

            DISPDBG( KE_WARNING, "Error initializing rumble feature for gamepad! "
               "Device ID:" << device_id <<
               "Joystick ID: " << handle.joystick_id <<
               "Error code:" << SDL_GetError() );
         }
      }
      else
      {
         /* This is not a rumble haptic */
         SDL_HapticClose( handle.haptic );
         handle.haptic = 0;
      }
   }

   /* Add this to the list of handles */
   GamepadHandles.push_back(handle);
}


/*
 * Name: KeOnGamepadButtonPress
 * Desc: Called when a gamepad button has been pressed
 */
void KeOnGamepadButtonPress( int device_id, void* context )
{
   SDL_ControllerButtonEvent* event = static_cast<SDL_ControllerButtonEvent*>( context );

   /* Search for the specified device and update the button info */

   std::vector<CKeGamepadHandle>::iterator i = GamepadHandles.begin();

   while( i != GamepadHandles.end() )
   {
      if( i->id == device_id )
      {
         i->state.buttons[event->button].pressed = event->state;
         i->state.buttons[event->button].timestamp = event->timestamp;

         return;
      }

      ++i;
   }
}


/*
 * Name: KeOnGamepadRemoved
 * Desc: Called when a gamepad has been removed/dettached.
 */
void KeOnGamepadRemoved( int device_id )
{
   /* Search for this ID, if we find it, go ahead and remove it after unintializing it. */

   std::vector<CKeGamepadHandle>::iterator i = GamepadHandles.begin();

   while( i != GamepadHandles.end() )
   {
      if( i->id == device_id )
      {
         GamepadHandles.erase(i);

         return;
      }

      ++i;
   }

}


/*
 * Name: KeGetGamepadState
 * Desc: Returns the input state of the specified gamepad
 */
bool KeGetGamepadState( int device_id, KeGamepadState* gamepad )
{
   std::vector<CKeGamepadHandle>::iterator i = GamepadHandles.begin();

   while( i != GamepadHandles.end() )
   {
      if( i->id == device_id )
      {
         memmove( gamepad, &i->state, sizeof( KeGamepadState ) );

         return true;
      }

      ++i;
   }

   return false;
}


And my event handler:

Code:
/*
 * Name: KeProcessEvents
 * Desc: Handles system events during the application's lifetime.
 * TODO: Setup callbacks for each event type.
 */
void KeProcessEvents()
{
   SDL_Event   event;
   
    /* Check for any SDL supported events */
    while( SDL_PollEvent( &event ) )
    {
        /* Respond to events accordingly */
        switch( event.type )
        {
            case SDL_QUIT:
            quitting = Yes;
                break;
               
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                KeProcessKeyEvent( &event );
                KeOnKeyboard( KeGetContextPointer(), &event );
                break;
               
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
                KeProcessMouseEvent( &event );
                KeOnMouse( KeGetContextPointer(), &event );
                break;
               
            case SDL_MOUSEMOTION:
                KeProcessMouseEvent( &event );
                break;
               
            case SDL_CONTROLLERBUTTONDOWN:
            case SDL_CONTROLLERBUTTONUP:
                KeOnGamepad( KeGetContextPointer(), &event );
            KeOnGamepadButtonPress( event.cbutton.which, &event.cbutton );
                break;

         case SDL_CONTROLLERAXISMOTION:
            break;

         case SDL_CONTROLLERDEVICEADDED:
            KeOnGamepadAdded( event.cdevice.which );
            break;

         case SDL_CONTROLLERDEVICEREMOVED:
            KeOnGamepadRemoved( event.cdevice.which );
            break;

         case SDL_JOYAXISMOTION:
         case SDL_JOYBALLMOTION:
         case SDL_JOYHATMOTION:
         case SDL_JOYBUTTONDOWN:
         case SDL_JOYBUTTONUP:
         case SDL_JOYDEVICEADDED:
         case SDL_JOYDEVICEREMOVED:
            _asm nop;
            break;
        }
    }
   
    /* Update keys */
    KeUpdateKeys();
}


If you want to see my engine's full source code, then take a look at https://github.com/blueshogun96/KunaiEngine

Now, I didn't add any code to deal with the joystick part (the non gamepads) because I wanted to add breakpoints into my IDE and see if the events are actually being fired. I've inserted breakpoints at every controller event, and the only one that gets triggered is SDL_CONTROLLERDEVICEADDED. When I remove a controller, nothing happens, but when I reattach the same one, I get that message triggered. Button presses and axis movement also doesn't work.

I've also had this problem with mouse input, but then all of a sudden, it started working. Maybe this will happen with my gamepad code too. Anyone else experiencing this? Devices I tried using: Xbox 360 and PS4 controllers and a Microsoft Sidewinder Freestyle Pro. OSes I've tried: Windows 7 and 8.1 (going to try MacOSX today). SDL versions used: 2.0.4 (June 27, 2015) and 2.0.3.

Shogun.
blueshogun96


Joined: 12 Jul 2015
Posts: 4
Oh yeah, I forgot to mention that the same thing happens with the joystick events. Only addition and removal events get triggered. Button presses do nothing.
blueshogun96


Joined: 12 Jul 2015
Posts: 4
Nevermind, it's my own code causing the problem. The deconstructor in my gamepad handle class gets called after adding it to the vector due to it going out of scope. I should have used a smart pointer instead to delay that. Thanks for reading.

Shogun.