1 // Copyright 2005-2019 The Mumble Developers. All rights reserved.
2 // Use of this source code is governed by a BSD-style license
3 // that can be found in the LICENSE file at the root of the
4 // Mumble source tree or at <https://www.mumble.info/LICENSE>.
5 
6 #include "mumble_pch.hpp"
7 
8 #include "XboxInput.h"
9 
10 const QUuid XboxInput::s_XboxInputGuid = QUuid(QString::fromLatin1("ca3937e3-640c-4d9e-9ef3-903f8b4fbcab"));
11 
XboxInput()12 XboxInput::XboxInput()
13 	: GetState(NULL)
14 	, m_getStateFunc(NULL)
15 	, m_getStateExFunc(NULL)
16 	, m_xinputlib(NULL)
17 	, m_valid(false) {
18 
19 	// Load the most suitable XInput DLL available.
20 	//
21 	// We prefer 1_4 and 1_3 over the others because they provide
22 	// XInputGetStateEx(), which allows us to query the state of
23 	// the guide button.
24 	//
25 	// See https://msdn.microsoft.com/en-us/library/windows/desktop/hh405051(v=vs.85).aspx
26 	// for more information.
27 	QStringList alternatives;
28 	alternatives << QLatin1String("XInput1_4.dll");
29 	alternatives << QLatin1String("xinput1_3.dll");
30 	alternatives << QLatin1String("XInput9_1_0.dll");
31 	alternatives << QLatin1String("xinput1_2.dll");
32 	alternatives << QLatin1String("xinput1_1.dll");
33 
34 	foreach(const QString &lib, alternatives) {
35 		m_xinputlib = LoadLibraryW(reinterpret_cast<const wchar_t *>(lib.utf16()));
36 		if (m_xinputlib != NULL) {
37 			qWarning("XboxInput: using XInput DLL '%s'", qPrintable(lib));
38 			m_valid = true;
39 			break;
40 		}
41 	}
42 
43 	if (!m_valid) {
44 		qWarning("XboxInput: no valid XInput DLL was found on the system.");
45 		return;
46 	}
47 
48 	m_getStateFunc = reinterpret_cast<XboxInputGetStateFunc>(GetProcAddress(m_xinputlib, "XInputGetState"));
49 	// Undocumented XInputGetStateEx -- ordinal 100. It is available in XInput 1.3 and greater.
50 	// It provides access to the state of the guide button.
51 	// For reference, see SDL's XInput support: http://www.libsdl.org/tmp/SDL/src/core/windows/SDL_xinput.c
52 	m_getStateExFunc = reinterpret_cast<XboxInputGetStateFunc>(GetProcAddress(m_xinputlib, (char *)100));
53 
54 	if (m_getStateExFunc != NULL) {
55 		GetState = m_getStateExFunc;
56 		qWarning("XboxInput: using XInputGetStateEx() as querying function.");
57 	} else if (m_getStateFunc != NULL) {
58 		GetState = m_getStateFunc;
59 		qWarning("XboxInput: using XInputGetState() as querying function.");
60 	} else {
61 		m_valid = false;
62 		qWarning("XboxInput: no valid querying function found.");
63 	}
64 }
65 
~XboxInput()66 XboxInput::~XboxInput() {
67 	if (m_xinputlib) {
68 		FreeLibrary(m_xinputlib);
69 	}
70 }
71 
isValid() const72 bool XboxInput::isValid() const {
73 	return m_valid;
74 }
75