all repos — mgba @ 1f156921732db400cfbb4a0ff3f8efc0faf5dd1e

mGBA Game Boy Advance Emulator

src/platform/qt/input/InputController.h (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#pragma once
  7
  8#include "GamepadAxisEvent.h"
  9#include "GamepadHatEvent.h"
 10#include "InputIndex.h"
 11
 12#include <memory>
 13
 14#include <QImage>
 15#include <QMap>
 16#include <QMutex>
 17#include <QObject>
 18#include <QSet>
 19#include <QTimer>
 20#include <QVector>
 21
 22#include <mgba/core/core.h>
 23#include <mgba/core/input.h>
 24
 25#include <mgba/gba/interface.h>
 26
 27#ifdef BUILD_SDL
 28#include "platform/sdl/sdl-events.h"
 29#endif
 30
 31#ifdef BUILD_QT_MULTIMEDIA
 32#include "VideoDumper.h"
 33#include <QCamera>
 34#endif
 35
 36struct mRotationSource;
 37struct mRumble;
 38
 39class QCamera;
 40class QMenu;
 41
 42namespace QGBA {
 43
 44class ConfigController;
 45class GameController;
 46class InputItem;
 47
 48class InputController : public QObject {
 49Q_OBJECT
 50
 51public:
 52	enum class CameraDriver : int {
 53		NONE = 0,
 54#ifdef BUILD_QT_MULTIMEDIA
 55		QT_MULTIMEDIA = 1,
 56#endif
 57	};
 58
 59	static const uint32_t KEYBOARD = 0x51545F4B;
 60
 61	InputController(int playerId = 0, QWidget* topLevel = nullptr, QObject* parent = nullptr);
 62	~InputController();
 63
 64	InputIndex* inputIndex() { return &m_inputIndex; }
 65	InputIndex* keyIndex() { return &m_keyIndex; }
 66	void rebuildIndex(const InputIndex* = nullptr);
 67	void rebuildKeyIndex(const InputIndex* = nullptr);
 68
 69	void addPlatform(mPlatform, const mInputPlatformInfo*);
 70	void setPlatform(mPlatform);
 71	void addKey(const QString& name);
 72
 73	void setConfiguration(ConfigController* config);
 74	void saveConfiguration();
 75	void loadConfiguration(uint32_t type);
 76	void loadProfile(uint32_t type, const QString& profile);
 77	void saveConfiguration(uint32_t type);
 78	void saveProfile(uint32_t type, const QString& profile);
 79	const char* profileForType(uint32_t type);
 80
 81	GBAKey mapKeyboard(int key) const;
 82
 83	void bindKey(uint32_t type, int key, GBAKey);
 84
 85	const mInputMap* map();
 86
 87	int pollEvents();
 88
 89	static const int32_t AXIS_THRESHOLD = 0x3000;
 90	QSet<int> activeGamepadButtons(int type);
 91	QSet<QPair<int, GamepadAxisEvent::Direction>> activeGamepadAxes(int type);
 92	QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(int type);
 93	void recalibrateAxes();
 94
 95	void bindKey(uint32_t type, int key, const QString&);
 96	void bindAxis(uint32_t type, int axis, GamepadAxisEvent::Direction, const QString&);
 97	void bindHat(uint32_t type, int hat, GamepadHatEvent::Direction, const QString&);
 98
 99	QStringList connectedGamepads(uint32_t type) const;
100	int gamepad(uint32_t type) const;
101	void setGamepad(uint32_t type, int index);
102	void setPreferredGamepad(uint32_t type, const QString& device);
103
104	void registerTiltAxisX(int axis);
105	void registerTiltAxisY(int axis);
106	void registerGyroAxisX(int axis);
107	void registerGyroAxisY(int axis);
108
109	float gyroSensitivity() const;
110	void setGyroSensitivity(float sensitivity);
111
112	void stealFocus(QWidget* focus);
113	void releaseFocus(QWidget* focus);
114
115	QList<QPair<QByteArray, QString>> listCameras() const;
116
117	mRumble* rumble();
118	mRotationSource* rotationSource();
119	mImageSource* imageSource() { return &m_image; }
120	GBALuminanceSource* luminance() { return &m_lux; }
121
122signals:
123	void profileLoaded(const QString& profile);
124	void luminanceValueChanged(int value);
125
126public slots:
127	void testGamepad(int type);
128	void updateJoysticks();
129	int updateAutofire();
130
131	void setAutofire(int key, bool enable);
132
133	// TODO: Move these to somewhere that makes sense
134	void suspendScreensaver();
135	void resumeScreensaver();
136	void setScreensaverSuspendable(bool);
137
138	void increaseLuminanceLevel();
139	void decreaseLuminanceLevel();
140	void setLuminanceLevel(int level);
141	void setLuminanceValue(uint8_t value);
142
143	void loadCamImage(const QString& path);
144	void setCamImage(const QImage& image);
145
146	void setCamera(const QByteArray& id);
147
148protected:
149	bool eventFilter(QObject*, QEvent*) override;
150
151private slots:
152#ifdef BUILD_QT_MULTIMEDIA
153	void prepareCamSettings(QCamera::Status);
154#endif
155	void setupCam();
156	void teardownCam();
157
158private:
159	void postPendingEvent(int key);
160	void clearPendingEvent(int key);
161	bool hasPendingEvent(int key) const;
162	void sendGamepadEvent(QEvent*);
163	void restoreModel();
164	void rebindKey(const QString& key);
165
166	InputItem* itemForKey(const QString& key);
167	int keyId(const QString& key);
168
169	InputIndex m_inputIndex;
170	InputIndex m_keyIndex;
171
172	struct InputControllerLux : GBALuminanceSource {
173		InputController* p;
174		uint8_t value;
175	} m_lux;
176	uint8_t m_luxValue;
177	int m_luxLevel;
178
179	struct InputControllerImage : mImageSource {
180		InputController* p;
181		QImage image;
182		QImage resizedImage;
183		bool outOfDate;
184		QMutex mutex;
185		unsigned w, h;
186	} m_image;
187
188#ifdef BUILD_QT_MULTIMEDIA
189	std::unique_ptr<QCamera> m_camera;
190	VideoDumper m_videoDumper;
191#endif
192
193	mInputMap m_inputMap;
194	int m_activeKeys;
195	bool m_autofireEnabled[32] = {};
196	int m_autofireStatus[32] = {};
197
198	ConfigController* m_config = nullptr;
199	int m_playerId;
200	QWidget* m_topLevel;
201	QWidget* m_focusParent;
202	QMap<mPlatform, const mInputPlatformInfo*> m_keyInfo;
203	const mInputPlatformInfo* m_activeKeyInfo = nullptr;
204
205	std::unique_ptr<QMenu> m_bindings;
206	std::unique_ptr<QMenu> m_autofire;
207
208#ifdef BUILD_SDL
209	static int s_sdlInited;
210	static mSDLEvents s_sdlEvents;
211	mSDLPlayer m_sdlPlayer{};
212	bool m_playerAttached = false;
213#endif
214
215	QVector<int> m_deadzones;
216
217	QSet<int> m_activeButtons;
218	QSet<QPair<int, GamepadAxisEvent::Direction>> m_activeAxes;
219	QSet<QPair<int, GamepadHatEvent::Direction>> m_activeHats;
220	QTimer m_gamepadTimer{nullptr};
221
222	QSet<int> m_pendingEvents;
223};
224
225}