Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

[input] Add 'Enable Joystick' to GUI settings. Fix for http://trac.xbmc.org/ticket/13146 #1111

Merged
merged 5 commits into from

6 participants

Karlson2k wsoltys jmarshallnz Memphiz gyunaev davilla
Karlson2k
Collaborator

Added GUI settings for control Joystick usage.
Some addition to CJoystick class - identical to CStatMouse.
Now Joystick can be enabled/disabled (and Initialized/deinitialized) by calling g_Joystick.SetEnable (true / false)

Also can be used as workaround for popular iMON (SoundGraph) hardware on Windows, which with latest DirectInput patches falls into endless Remove/Insert loop. That's make remote iMon control and display unusable.

wsoltys
Collaborator

I don't think that I like that. As I can see from the imon thread this is a bug in the imon firmware and I don't want to fix their shit in our code.
Since I can't test it I would appreciate a real and more general fix if possible.

wsoltys
Collaborator

btw for your next pr please make sure that you don't have the merge branch thingies in. Try something like git pull --rebase upstream master to get your changes on top without the merge.

Karlson2k
Collaborator

iMon claims that this it the bug in DirectX. See 'Cause' in http://www.soundgraph.com/forums/faq.php?faq=sg_faq_sw_imon_manager_g_01#faq_sg_faq_software_products_gamecontrol
But anyway - it's unfixable because firmware isn't upgradeable. At least until Microsoft rewrote DirectInput code. :)
So, until that it's not possible to use iMON hardware with XBMC (with DirectInput Joystick). I'm sure that a lot of users will be unhappy if this will go to release.
My solution is relatively simple, doesn't broke anything and add small feature, that can be used even by users without iMON hardware.

jmarshallnz
Owner

Putting aside the issue of whether we want it, the above 3 commits could be squashed into one, plus some of the checks (in ProcessEventClient) aren't needed - they don't actually use the joystick hardware stuff, rather they use the joystick keymapping stuff. Also, there's some whitespace issues on the last commit.

To squash into one, git rebase -i HEAD~3 and change the last 2 commits to squash. You'll then get to rewrite the commit message.

wsoltys
Collaborator

To get you into thinking, is there a possibility to detect the firmware in question? Maybe via a key in the registry or a certain dll which is there?

Karlson2k
Collaborator

OK, I'll combine all commits in one, fix whitespaces and remove some checks.
It's possible to detect hardware via USB HID properties, but I don't have a lists of buggy and bug-free firmwares.
I'm ready to write detection module. Could you advise something about lists of the hardware?

Karlson2k
Collaborator

Started development thread for discussion: http://forum.xbmc.org/showthread.php?tid=135218

Karlson2k
Collaborator

Rewrote from the scratch.
Now it looks like elegant solution, not like a hack as before

wsoltys
Collaborator

I like the idea with the gui settings but you mixed too many different changes into one commit which makes it difficult to review. One commit for the gui setting and one commit for the cosmetic changes please.
I don't know what the asm fix has to do with the joystick class nor this pr in general.

Karlson2k
Collaborator

There are just a few cosmetic points.
One of them - duplicated Reset, other - code for one function move from .h to .cpp and third one - move g_Joystick to SystemGlobal.
Do you really need separate commits?

wsoltys
Collaborator

@jmarshallnz what do you think? can this go in?

Karlson2k
Collaborator

OK. I'll split it to several commits. :)

wsoltys
Collaborator

Just two are fine :)

Karlson2k
Collaborator

Too late. :)

Karlson2k
Collaborator

@jmarshallnz . Fine?

jmarshallnz
Owner

Karlson2k: yes - please squash that one down, remove the russian translation, fix the Reset issue, and separate out your one-line if()'s onto two lines.

Karlson2k
Collaborator

It was done already, except squash.

jmarshallnz
Owner

Looks fine - please squash the fixups into the appropriate commits and I'll pull it in.

Karlson2k
Collaborator

@jmarshallnz finally done!

jmarshallnz jmarshallnz was assigned
jmarshallnz jmarshallnz merged commit ba554f1 into from
jmarshallnz
Owner

Thanks :)

gyunaev
Collaborator

This breaks the configurations with --disable-joystick:

CPP xbmc/SystemGlobals.o
SystemGlobals.cpp:68:3: error: ‘CJoystick’ does not name a type

Looks like just the || defined HAS_EVENT_SERVER needs removing on the include and g_Joystick?

Collaborator

That indeed fixed it for me and so far the compiled binary seem to work fine. Is there any other reason for having the HAS_EVENT_SERVER there?

Collaborator

HAS_EVENT_SERVER is there because the apple remote uses the joystick interface. If you break that, then the Apple remote will not work anymore if --disable-joystick is used which ios does in configure.in

arm-apple-darwin*)
use_joystick=no

Doesn't it just use the joystick translation stuff, not the actual joystick object (g_Joystick) ?

Collaborator

was that moved out ? from what I remember, there are functions there that the eventserver called which is why there was an || HAS_EVENT_SERVER

and it's osx not ios that uses the joystick/eventserver. other eventclients might also be using it.

Collaborator

Looks like "|| HAS_EVENT_SERVER" could be removed from SystemGlobals.cpp and from Application.cpp.
Now SystemGlobals just reflect include schema from Application.cpp.
CApplication::ProcessEventServer calls CApplication::ProcessJoystickEvent which one calls g_Joystick.Reset() (only ifdef HAS_SDL_JOYSTICK) and calls CButtonTranslator::GetInstance().TranslateJoystickString which one is using only defines JACTIVE_ from WIN/SDLJoystick.h
So now it doesn't break anything, but could be optimized.
Could someone test compilation on MacOS/iOS and Linux platforms to be sure?

Collaborator

I can confirm that Linux builds and works fine with || HASEVENT_SERVER removed when configured with --disabled-joystick (my standard build configuration)

Collaborator

@gyunaev thanks!
Still need MacOS/iOS confirmation.

Owner

Confirmed - removing the || HASEVENT_SERVER fixes compilation on ios/osx too.

Collaborator

Created PR #1140

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
8 language/English/strings.po
View
@@ -9294,7 +9294,13 @@ msgctxt "#35009"
msgid "Do not use the custom keymap for this device"
msgstr ""
-#empty strings from id 35010 to 35499
+#empty strings from id 35010 to 35099
+
+msgctxt "#35100"
+msgid "Enable joystick and gamepad support"
+msgstr ""
+
+#empty strings from id 35101 to 35499
msgctxt "#35500"
msgid "Location"
9 xbmc/Application.cpp
View
@@ -1351,7 +1351,7 @@ bool CApplication::Initialize()
ResetScreenSaver();
#ifdef HAS_SDL_JOYSTICK
- g_Joystick.Initialize();
+ g_Joystick.SetEnabled(g_guiSettings.GetBool("input.enablejoystick"));
#endif
return true;
@@ -2813,8 +2813,9 @@ bool CApplication::ProcessGamepad(float frameTime)
#ifdef HAS_SDL_JOYSTICK
if (!m_AppFocused)
return false;
+
int iWin = GetActiveWindowID();
- int bid;
+ int bid = 0;
g_Joystick.Update();
if (g_Joystick.GetButton(bid))
{
@@ -2873,7 +2874,7 @@ bool CApplication::ProcessGamepad(float frameTime)
g_Joystick.ResetAxis(abs(bid));
}
}
- int position;
+ int position = 0;
if (g_Joystick.GetHat(bid, position))
{
// reset Idle Timer
@@ -2892,7 +2893,7 @@ bool CApplication::ProcessGamepad(float frameTime)
bid = position<<16|bid;
- if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
+ if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
{
CAction action(actionID, 1.0f, 0.0f, actionName);
g_audioManager.PlayActionSound(action);
10 xbmc/SystemGlobals.cpp
View
@@ -41,6 +41,13 @@
#ifdef HAS_PYTHON
#include "interfaces/python/XBPython.h"
#endif
+#if defined(TARGET_WINDOWS)
+#include "input/windows/WINJoystick.h"
+#elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
+#include "input/SDLJoystick.h"
+#endif
+
+
CGUISettings g_guiSettings;
CSettings g_settings;
@@ -57,6 +64,9 @@
CGUITextureManager g_TextureManager;
CGUILargeTextureManager g_largeTextureManager;
CMouseStat g_Mouse;
+#if defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
+ CJoystick g_Joystick;
+#endif
CGUIPassword g_passwordManager;
CGUIInfoManager g_infoManager;
79 xbmc/input/SDLJoystick.cpp
View
@@ -32,11 +32,10 @@
using namespace std;
-CJoystick g_Joystick; // global
-
CJoystick::CJoystick()
{
- Reset();
+ Reset(true);
+ m_joystickEnabled = false;
m_NumAxes = 0;
m_AxisId = 0;
m_JoyId = 0;
@@ -44,13 +43,20 @@ CJoystick::CJoystick()
m_HatId = 0;
m_HatState = SDL_HAT_CENTERED;
m_ActiveFlags = JACTIVE_NONE;
- for (int i = 0 ; i<MAX_AXES ; i++)
- m_Amount[i] = 0;
SetDeadzone(0);
}
void CJoystick::Initialize()
{
+ if (!IsEnabled())
+ return;
+
+ if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0)
+ {
+ CLog::Log(LOGERROR, "(Re)start joystick subsystem failed : %s",SDL_GetError());
+ return;
+ }
+
// clear old joystick names
m_JoystickNames.clear();
@@ -108,7 +114,7 @@ void CJoystick::Initialize()
SDL_JoystickEventState(SDL_DISABLE);
}
-void CJoystick::Reset(bool axis)
+void CJoystick::Reset(bool axis /*=false*/)
{
if (axis)
{
@@ -122,6 +128,9 @@ void CJoystick::Reset(bool axis)
void CJoystick::Update()
{
+ if (!IsEnabled())
+ return;
+
int buttonId = -1;
int axisId = -1;
int hatId = -1;
@@ -236,6 +245,9 @@ void CJoystick::Update()
void CJoystick::Update(SDL_Event& joyEvent)
{
+ if (!IsEnabled())
+ return;
+
int buttonId = -1;
int axisId = -1;
int joyId = -1;
@@ -303,8 +315,11 @@ void CJoystick::Update(SDL_Event& joyEvent)
bool CJoystick::GetHat(int &id, int &position,bool consider_repeat)
{
- if (!IsHatActive())
+ if (!IsEnabled() || !IsHatActive())
+ {
+ id = position = 0;
return false;
+ }
position = m_HatState;
id = m_HatId;
if (!consider_repeat)
@@ -336,8 +351,11 @@ bool CJoystick::GetHat(int &id, int &position,bool consider_repeat)
bool CJoystick::GetButton(int &id, bool consider_repeat)
{
- if (!IsButtonActive())
+ if (!IsEnabled() || !IsButtonActive())
+ {
+ id = 0;
return false;
+ }
if (!consider_repeat)
{
id = m_ButtonId;
@@ -372,6 +390,17 @@ bool CJoystick::GetButton(int &id, bool consider_repeat)
return true;
}
+bool CJoystick::GetAxis (int &id)
+{
+ if (!IsEnabled() || !IsAxisActive())
+ {
+ id = 0;
+ return false;
+ }
+ id = m_AxisId;
+ return true;
+}
+
int CJoystick::GetAxisWithMaxAmount()
{
static int maxAmount;
@@ -401,6 +430,20 @@ float CJoystick::GetAmount(int axis)
return 0;
}
+void CJoystick::SetEnabled(bool enabled /*=true*/)
+{
+ if( enabled && !m_joystickEnabled )
+ {
+ m_joystickEnabled = true;
+ Initialize();
+ }
+ else if( !enabled && m_joystickEnabled )
+ {
+ ReleaseJoysticks();
+ m_joystickEnabled = false;
+ }
+}
+
float CJoystick::SetDeadzone(float val)
{
if (val<0) val=0;
@@ -409,8 +452,16 @@ float CJoystick::SetDeadzone(float val)
return val;
}
-bool CJoystick::Reinitialize()
+bool CJoystick::ReleaseJoysticks()
{
+ m_pJoysticks.clear();
+ m_JoystickNames.clear();
+ m_HatId = 0;
+ m_ButtonId = 0;
+ m_HatState = SDL_HAT_CENTERED;
+ m_ActiveFlags = JACTIVE_NONE;
+ Reset(true);
+
// Restart SDL joystick subsystem
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
if (SDL_WasInit(SDL_INIT_JOYSTICK) != 0)
@@ -418,12 +469,12 @@ bool CJoystick::Reinitialize()
CLog::Log(LOGERROR, "Stop joystick subsystem failed");
return false;
}
- if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0)
- {
- CLog::Log(LOGERROR, "Restart joystick subsystem failed : %s",SDL_GetError());
- return false;
- }
+ return true;
+}
+bool CJoystick::Reinitialize()
+{
+ if( !ReleaseJoysticks() ) return false;
Initialize();
return true;
7 xbmc/input/SDLJoystick.h
View
@@ -57,12 +57,14 @@ class CJoystick
void Update();
void Update(SDL_Event& event);
bool GetButton (int& id, bool consider_repeat=true);
- bool GetAxis (int &id) { if (!IsAxisActive()) return false; id=m_AxisId; return true; }
+ bool GetAxis (int &id);
bool GetHat (int &id, int &position, bool consider_repeat=true);
std::string GetJoystick() { return (m_JoyId>-1)?m_JoystickNames[m_JoyId]:""; }
int GetAxisWithMaxAmount();
float GetAmount(int axis);
float GetAmount() { return GetAmount(m_AxisId); }
+ bool IsEnabled() const { return m_joystickEnabled; }
+ void SetEnabled(bool enabled = true);
float SetDeadzone(float val);
bool Reinitialize();
@@ -74,6 +76,8 @@ class CJoystick
bool IsAxisActive() { return (m_ActiveFlags & JACTIVE_AXIS) == JACTIVE_AXIS; }
bool IsHatActive() { return (m_ActiveFlags & JACTIVE_HAT) == JACTIVE_HAT; }
+ bool ReleaseJoysticks();
+
int m_Amount[MAX_AXES];
int m_AxisId;
int m_ButtonId;
@@ -82,6 +86,7 @@ class CJoystick
int m_JoyId;
int m_NumAxes;
int m_DeadzoneRange;
+ bool m_joystickEnabled;
uint32_t m_pressTicksButton;
uint32_t m_pressTicksHat;
uint8_t m_ActiveFlags;
59 xbmc/input/windows/WINJoystick.cpp
View
@@ -31,8 +31,6 @@
using namespace std;
-CJoystick g_Joystick; // global
-
extern HWND g_hWnd;
#define MAX_AXISAMOUNT 32768
@@ -53,7 +51,8 @@ extern HWND g_hWnd;
CJoystick::CJoystick()
{
- Reset();
+ Reset(true);
+ m_joystickEnabled = false;
m_NumAxes = 0;
m_AxisId = 0;
m_JoyId = 0;
@@ -61,8 +60,6 @@ CJoystick::CJoystick()
m_HatId = 0;
m_HatState = SDL_HAT_CENTERED;
m_ActiveFlags = JACTIVE_NONE;
- for (int i = 0 ; i<MAX_AXES ; i++)
- m_Amount[i] = 0;
SetDeadzone(0);
m_pDI = NULL;
@@ -88,6 +85,13 @@ void CJoystick::ReleaseJoysticks()
m_pJoysticks.clear();
m_JoystickNames.clear();
m_devCaps.clear();
+ m_HatId = 0;
+ m_ButtonId = 0;
+ m_HatState = SDL_HAT_CENTERED;
+ m_ActiveFlags = JACTIVE_NONE;
+ Reset(true);
+ m_lastPressTicks = 0;
+ m_lastTicks = 0;
// Release any DirectInput objects.
SAFE_RELEASE( m_pDI );
}
@@ -172,6 +176,9 @@ BOOL CALLBACK CJoystick::EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdid
void CJoystick::Initialize()
{
+ if (!IsEnabled())
+ return;
+
HRESULT hr;
// clear old joystick names
@@ -208,7 +215,7 @@ void CJoystick::Initialize()
SetDeadzone(g_advancedSettings.m_controllerDeadzone);
}
-void CJoystick::Reset(bool axis)
+void CJoystick::Reset(bool axis /*=true*/)
{
if (axis)
{
@@ -222,6 +229,9 @@ void CJoystick::Reset(bool axis)
void CJoystick::Update()
{
+ if (!IsEnabled())
+ return;
+
int buttonId = -1;
int axisId = -1;
int hatId = -1;
@@ -360,8 +370,11 @@ void CJoystick::Update()
bool CJoystick::GetHat(int &id, int &position,bool consider_repeat)
{
- if (!IsHatActive())
+ if (!IsEnabled() || !IsHatActive())
+ {
+ id = position = 0;
return false;
+ }
position = m_HatState;
id = m_HatId;
if (!consider_repeat)
@@ -391,8 +404,11 @@ bool CJoystick::GetHat(int &id, int &position,bool consider_repeat)
bool CJoystick::GetButton(int &id, bool consider_repeat)
{
- if (!IsButtonActive())
+ if (!IsEnabled() || !IsButtonActive())
+ {
+ id = 0;
return false;
+ }
if (!consider_repeat)
{
id = m_ButtonId;
@@ -425,6 +441,17 @@ bool CJoystick::GetButton(int &id, bool consider_repeat)
return true;
}
+bool CJoystick::GetAxis (int &id)
+{
+ if (!IsEnabled() || !IsAxisActive())
+ {
+ id = 0;
+ return false;
+ }
+ id = m_AxisId;
+ return true;
+}
+
int CJoystick::GetAxisWithMaxAmount()
{
int maxAmount = 0;
@@ -452,6 +479,20 @@ float CJoystick::GetAmount(int axis)
return 0;
}
+void CJoystick::SetEnabled(bool enabled /*=true*/)
+{
+ if( enabled && !m_joystickEnabled )
+ {
+ m_joystickEnabled = true;
+ Initialize();
+ }
+ else if( !enabled && m_joystickEnabled )
+ {
+ ReleaseJoysticks();
+ m_joystickEnabled = false;
+ }
+}
+
float CJoystick::SetDeadzone(float val)
{
if (val<0) val=0;
@@ -468,6 +509,8 @@ bool CJoystick::Reinitialize()
void CJoystick::Acquire()
{
+ if (!IsEnabled())
+ return;
if(!m_pJoysticks.empty())
{
CLog::Log(LOGDEBUG, __FUNCTION__": Focus back, acquire Joysticks");
5 xbmc/input/windows/WINJoystick.h
View
@@ -47,12 +47,14 @@ class CJoystick
void ResetAxis(int axisId) { m_Amount[axisId] = 0; }
void Update();
bool GetButton (int& id, bool consider_repeat=true);
- bool GetAxis (int &id) { if (!IsAxisActive()) return false; id=m_AxisId; return true; }
+ bool GetAxis (int &id);
bool GetHat (int &id, int &position, bool consider_repeat=true);
std::string GetJoystick() { return (m_JoyId>-1)?m_JoystickNames[m_JoyId]:""; }
int GetAxisWithMaxAmount();
float GetAmount(int axis);
float GetAmount() { return GetAmount(m_AxisId); }
+ bool IsEnabled() const { return m_joystickEnabled; }
+ void SetEnabled(bool enabled = true);
float SetDeadzone(float val);
bool Reinitialize();
void Acquire();
@@ -77,6 +79,7 @@ class CJoystick
int m_JoyId;
int m_NumAxes;
int m_DeadzoneRange;
+ bool m_joystickEnabled;
uint32_t m_pressTicksButton;
uint32_t m_pressTicksHat;
uint8_t m_ActiveFlags;
3  xbmc/settings/GUISettings.cpp
View
@@ -520,6 +520,9 @@ void CGUISettings::Initialize()
#else
AddBool(in, "input.enablemouse", 21369, true);
#endif
+#if defined(HAS_SDL_JOYSTICK)
+ AddBool(in, "input.enablejoystick", 35100, true);
+#endif
CSettingsCategory* net = AddCategory(4, "network", 798);
if (g_application.IsStandAlone())
11 xbmc/settings/GUIWindowSettingsCategory.cpp
View
@@ -92,6 +92,11 @@
#include "Settings.h"
#include "AdvancedSettings.h"
#include "input/MouseStat.h"
+#if defined(TARGET_WINDOWS)
+#include "input/windows/WINJoystick.h"
+#elif defined(HAS_SDL_JOYSTICK)
+#include "input/SDLJoystick.h"
+#endif
#include "guilib/LocalizeStrings.h"
#include "LangInfo.h"
#include "utils/StringUtils.h"
@@ -1388,6 +1393,12 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC
{
g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse"));
}
+ else if (strSetting.Equals("input.enablejoystick"))
+ {
+#if defined(HAS_SDL_JOYSTICK)
+ g_Joystick.SetEnabled(g_guiSettings.GetBool("input.enablejoystick"));
+#endif
+ }
else if (strSetting.Equals("videoscreen.screen"))
{
DisplayMode mode = g_guiSettings.GetInt("videoscreen.screen");
Something went wrong with that request. Please try again.