mgba-ps3/src/platform/qt/InputController.h
2023-12-20 22:59:35 -08:00

199 lines
5.0 KiB
C++

/* Copyright (c) 2013-2023 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once
#include "input/GamepadAxisEvent.h"
#include "input/GamepadHatEvent.h"
#include "input/InputDriver.h"
#include "input/InputMapper.h"
#include <QHash>
#include <QImage>
#include <QMutex>
#include <QReadWriteLock>
#include <QObject>
#include <QSet>
#include <QTimer>
#include <QVector>
#include <memory>
#include <mgba/core/input.h>
#include <mgba/gba/interface.h>
#ifdef BUILD_QT_MULTIMEDIA
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
#include "VideoDumper.h"
#endif
#include <QCamera>
#endif
struct mRotationSource;
struct mRumble;
namespace QGBA {
class ConfigController;
class Gamepad;
class InputSource;
class InputController : public QObject {
Q_OBJECT
public:
enum class CameraDriver : int {
NONE = 0,
#ifdef BUILD_QT_MULTIMEDIA
QT_MULTIMEDIA = 1,
#endif
};
static const uint32_t KEYBOARD = 0x51545F4B;
InputController(QWidget* topLevel = nullptr, QObject* parent = nullptr);
~InputController();
void addInputDriver(std::shared_ptr<InputDriver>);
int playerId() const { return m_playerId; }
void setConfiguration(ConfigController* config);
void saveConfiguration();
bool loadConfiguration(uint32_t type);
bool loadProfile(uint32_t type, const QString& profile);
void saveConfiguration(uint32_t type);
void saveProfile(uint32_t type, const QString& profile);
QString profileForType(uint32_t type);
int mapKeyboard(int key) const;
mInputMap* map() { return &m_inputMap; }
const mInputMap* map() const { return &m_inputMap; }
int pollEvents();
static const int32_t AXIS_THRESHOLD = 0x3000;
void setGamepadDriver(uint32_t type);
const InputDriver* gamepadDriver() const { return m_inputDrivers.value(m_gamepadDriver).get(); }
InputDriver* gamepadDriver() { return m_inputDrivers.value(m_gamepadDriver).get(); }
QStringList connectedGamepads(uint32_t type = 0) const;
int gamepadIndex(uint32_t type = 0) const;
void setGamepad(uint32_t type, int index);
void setGamepad(int index);
void setPreferredGamepad(uint32_t type, int index);
void setPreferredGamepad(int index);
InputMapper mapper(uint32_t type);
InputMapper mapper(InputDriver*);
InputMapper mapper(InputSource*);
void setSensorDriver(uint32_t type);
const InputDriver* sensorDriver() const { return m_inputDrivers.value(m_sensorDriver).get(); }
InputDriver* sensorDriver() { return m_inputDrivers.value(m_sensorDriver).get(); }
void stealFocus(QWidget* focus);
void releaseFocus(QWidget* focus);
QList<QPair<QByteArray, QString>> listCameras() const;
mRumble* rumble();
mRotationSource* rotationSource();
mImageSource* imageSource() { return &m_image; }
GBALuminanceSource* luminance() { return &m_lux; }
signals:
void updated();
void profileLoaded(const QString& profile);
void luminanceValueChanged(int value);
public slots:
void testGamepad(uint32_t type);
void update();
void increaseLuminanceLevel();
void decreaseLuminanceLevel();
void setLuminanceLevel(int level);
void setLuminanceValue(uint8_t value);
void loadCamImage(const QString& path);
void setCamImage(const QImage& image);
void setCamera(const QByteArray& id);
private slots:
#ifdef BUILD_QT_MULTIMEDIA
void prepareCamSettings(QCamera::Status);
#endif
void setupCam();
void teardownCam();
private:
void postPendingEvent(int key);
void clearPendingEvent(int key);
void postPendingEvents(int keys);
void clearPendingEvents(int keys);
bool hasPendingEvent(int key) const;
void sendGamepadEvent(QEvent*);
static int claimPlayer();
static void freePlayer(int);
std::shared_ptr<Gamepad> gamepad(uint32_t type);
QList<std::shared_ptr<Gamepad>> gamepads();
QSet<int> activeGamepadButtons(uint32_t type);
QSet<QPair<int, GamepadAxisEvent::Direction>> activeGamepadAxes(uint32_t type);
QSet<QPair<int, GamepadHatEvent::Direction>> activeGamepadHats(uint32_t type);
struct InputControllerLux : GBALuminanceSource {
InputController* p;
uint8_t value;
} m_lux;
uint8_t m_luxValue;
int m_luxLevel;
struct InputControllerImage : mImageSource {
InputController* p;
QImage image;
QImage resizedImage;
bool outOfDate;
QMutex mutex;
int w, h;
} m_image;
#ifdef BUILD_QT_MULTIMEDIA
bool m_cameraActive = false;
QByteArray m_cameraDevice;
std::unique_ptr<QCamera> m_camera;
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
VideoDumper m_videoDumper;
#endif
#endif
static int s_claimedPlayers;
mInputMap m_inputMap;
ConfigController* m_config = nullptr;
int m_playerId;
QWidget* m_topLevel;
QWidget* m_focusParent;
QHash<uint32_t, std::shared_ptr<InputDriver>> m_inputDrivers;
uint32_t m_gamepadDriver = 0;
uint32_t m_sensorDriver = 0;
QSet<int> m_activeButtons;
QSet<QPair<int, GamepadAxisEvent::Direction>> m_activeAxes;
QSet<QPair<int, GamepadHatEvent::Direction>> m_activeHats;
QTimer m_gamepadTimer{nullptr};
QSet<int> m_pendingEvents;
QReadWriteLock m_eventsLock;
};
}