Browse Source

InputSDL: distinguish between repeat buttons and single shot buttons

This makes navigating the interface much smoother than it was, and
doesn't require external software to translate button presses into
keyboard commands.

Also added Support for xbox controller on Windows out of the box

Plex-CLA-1.0-signed-off-by: Cory Parsons <babylonstudio@gmail.com>
Cory Parsons 9 years ago
parent
commit
c254ed2b57

+ 1 - 1
resources/inputmaps/wiimote.json

@@ -10,4 +10,4 @@
       "KEY_BUTTON_10": "enter",
       "KEY_BUTTON_9": "back"
   }
-}
+}

+ 0 - 0
resources/inputmaps/xbox-controller.json → resources/inputmaps/xbox-controller-mac.json


+ 39 - 0
resources/inputmaps/xbox-controller-windows.json

@@ -0,0 +1,39 @@
+{
+  "name": "Xbox Controller",
+  "idmatcher": "XInput.*",
+  "mapping": 
+  {
+      // left stick L,R,U,D, click
+      "KEY_AXIS_0_VAL_DOWN": "",
+      "KEY_AXIS_0_VAL_UP": "",
+      "KEY_AXIS_1_VAL_DOWN": "",
+      "KEY_AXIS_1_VAL_UP": "",
+      "KEY_BUTTON_6": "",
+      // right stick L,R,U,D, click
+      "KEY_AXIS_2_VAL_DOWN": "host:player:add volume -1",
+      "KEY_AXIS_2_VAL_UP": "host:player:add volume 1",
+      "KEY_AXIS_3_VAL_DOWN": "host:player:add volume 1",
+      "KEY_AXIS_3_VAL_UP": "host:player:add volume -1",
+      "KEY_BUTTON_7": "host:player:cycle mute",
+      // DPAD U,D,L,R
+      "KEY_BUTTON_0": "up",
+      "KEY_BUTTON_1": "down",
+      "KEY_BUTTON_2": "left",
+      "KEY_BUTTON_3": "right",
+      // BACK, HOME, START
+      "KEY_BUTTON_5": "host:fullscreen",
+      "KEY_BUTTON_14": "host:toggleDebug",
+      "KEY_BUTTON_4": "home",
+      // LB, LT
+      "KEY_BUTTON_8": "host:player:seek -15",
+      "KEY_AXIS_4_VAL_DOWN": "",
+      // RB, RT
+      "KEY_BUTTON_9": "host:player:seek 15",
+      "KEY_AXIS_4_VAL_DOWN": "",
+      // A, B, X, Y
+      "KEY_BUTTON_10": "enter",
+      "KEY_BUTTON_11": "back",
+      "KEY_BUTTON_12": "cycle_subtitles",
+      "KEY_BUTTON_13": "host:player:cycle mute"
+  }
+}

+ 35 - 17
src/input/InputSDL.cpp

@@ -64,6 +64,8 @@ void InputSDLWorker::run()
 {
   QElapsedTimer polltimer;
 
+  QHash<int,int> repeats;
+
   while (true)
   {
     SDL_Event event;
@@ -82,22 +84,31 @@ void InputSDLWorker::run()
         case SDL_JOYBUTTONDOWN:
         {
           QLOG_DEBUG() << "SDL Got button down for button #" << event.jbutton.button
-                      << " on Joystick #" << event.jbutton.which;
-          QElapsedTimer* timer = new QElapsedTimer();
-          m_buttonTimestamps[event.jbutton.button] = timer;
-          timer->start();
+                       << " on Joystick #" << event.jbutton.which;
+          // emit that the button has gone down
+          emit receivedInput(nameForId(event.jbutton.which), QString("KEY_BUTTON_%1").arg(event.jbutton.button));
+          
+          // set up the repeat timer for this button
+          QElapsedTimer* repeatTimer = new QElapsedTimer();
+          m_buttonTimestamps[event.jbutton.button] = repeatTimer;
+          repeatTimer->start();
+          // reset the repeat count for this button
+          repeats[event.jbutton.button] = 0;
           break;
         }
 
         case SDL_JOYBUTTONUP:
         {
           if (m_buttonTimestamps[event.jbutton.button])
-          {
-            emit receivedInput(nameForId(event.jbutton.which), QString("KEY_BUTTON_%1").arg(event.jbutton.button));
+          {          
+            // remove the repeat timer for this button
             delete m_buttonTimestamps[event.jbutton.button];
             m_buttonTimestamps.remove(event.jbutton.button);
           }
 
+          // reset the repeat count
+          repeats[event.jbutton.button] = 0;
+
           break;
         }
 
@@ -117,10 +128,10 @@ void InputSDLWorker::run()
 
         case SDL_JOYAXISMOTION:
         {
-          int deadband = 32768 *0.05;
+          int deadband = 32768 * 0.15;
 
           // handle the analog value push
-          // keep a dead band of 5%
+          // keep a dead band of 15%
           if (std::abs(event.jaxis.value) > deadband)
           {
             // normalize the value
@@ -162,27 +173,34 @@ void InputSDLWorker::run()
       }
     }
 
-    // check for longpresses
+    // check for long press and repeats
     SDLTimeStampMapIterator it = m_buttonTimestamps.constBegin();
     while (it != m_buttonTimestamps.constEnd())
     {
       if (it.value())
       {
-        if (m_buttonTimestamps[it.key()]->elapsed() > SDL_BUTTON_LONGPRESS_DELAY)
+        // repeat at a rate of SDL_BUTTON_REPEAT_RATE
+        if (repeats[it.key()] > 0 && m_buttonTimestamps[it.key()]->elapsed() > SDL_BUTTON_REPEAT_RATE)
         {
-          QLOG_DEBUG() << "SDL Got button longpress for button #" << event.jbutton.button
-                      << " on Joystick #" << event.jbutton.which;
-          emit receivedInput(nameForId(event.jbutton.which), QString("KEY_BUTTON_%1_LONG").arg(it.key()));
-          delete it.value();
-          m_buttonTimestamps.remove(it.key());
+          QLOG_DEBUG() << QString("SDL Got button repeat(%1) for button #").arg(repeats[it.key()]) << event.jbutton.button
+                       << " on Joystick #" << event.jbutton.which;
+          emit receivedInput(nameForId(event.jbutton.which), QString("KEY_BUTTON_%1").arg(it.key()));
+
+          m_buttonTimestamps[it.key()]->restart();
           it = m_buttonTimestamps.constBegin();
+
+          repeats[it.key()]++;
           continue;
         }
+        else
+        {
+          // only start repeating if SDL_BUTTON_REPEAT_DELAY time has passed
+          if (m_buttonTimestamps[it.key()]->elapsed() > SDL_BUTTON_REPEAT_DELAY)
+            repeats[it.key()]++;
+        }
       }
       else
       {
-        m_buttonTimestamps.remove(it.key());
-        it = m_buttonTimestamps.constBegin();
         continue;
       }
 

+ 2 - 1
src/input/InputSDL.h

@@ -23,7 +23,8 @@ typedef QMap<int, QElapsedTimer*> SDLTimeStampMap;
 typedef QMap<int, QElapsedTimer*>::const_iterator SDLTimeStampMapIterator;
 
 #define SDL_POLL_TIME 50
-#define SDL_BUTTON_LONGPRESS_DELAY 500
+#define SDL_BUTTON_REPEAT_DELAY 500
+#define SDL_BUTTON_REPEAT_RATE 100
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 class InputSDLWorker : public QObject