Skip to content

Commit

Permalink
Joystick: Convert Manager from Tool To Singleton
Browse files Browse the repository at this point in the history
  • Loading branch information
HTRamsey committed Oct 25, 2024
1 parent 0df702a commit 78f8fca
Show file tree
Hide file tree
Showing 20 changed files with 126 additions and 161 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ if(ANDROID)
endif()
endif()

set(QT_SILENCE_MISSING_DEPENDENCY_TARGET_WARNING ON)

find_package(Qt6
REQUIRED
COMPONENTS
Expand Down
2 changes: 1 addition & 1 deletion src/API/QGCCorePlugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ QQmlApplicationEngine* QGCCorePlugin::createQmlApplicationEngine(QObject* parent
{ "eventMonitor", QVariant::fromValue(&eventMonitor) }
}); */
qmlEngine->addImportPath("qrc:/qml");
qmlEngine->rootContext()->setContextProperty("joystickManager", qgcApp()->toolbox()->joystickManager());
qmlEngine->rootContext()->setContextProperty("joystickManager", JoystickManager::instance());
qmlEngine->rootContext()->setContextProperty("debugMessageModel", AppMessages::getModel());
return qmlEngine;
}
Expand Down
5 changes: 2 additions & 3 deletions src/Camera/QGCCameraManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,8 @@ void QGCCameraManager::_vehicleReady(bool ready)
if(ready) {
if(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle() == _vehicle) {
_vehicleReadyState = true;
JoystickManager *pJoyMgr = qgcApp()->toolbox()->joystickManager();
_activeJoystickChanged(pJoyMgr->activeJoystick());
connect(pJoyMgr, &JoystickManager::activeJoystickChanged, this, &QGCCameraManager::_activeJoystickChanged);
_activeJoystickChanged(JoystickManager::instance()->activeJoystick());
connect(JoystickManager::instance(), &JoystickManager::activeJoystickChanged, this, &QGCCameraManager::_activeJoystickChanged);
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/Joystick/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ qt_add_resources(Joystick "gamecontrollerdb.txt"
FILES ${sdl_gamecontrollerdb_SOURCE_DIR}/gamecontrollerdb.txt
)

qt_add_qml_module(Joystick
URI QGroundControl.JoystickManager
VERSION 1.0
OUTPUT_TARGETS Joystick_targets
IMPORT_PATH ${QT_QML_OUTPUT_DIRECTORY}
)

cmake_print_variables(Joystick_targets)

set(MINIMUM_SDL2_VERSION 2.30.0)

if(NOT QGC_BUILD_DEPENDENCIES)
Expand Down
1 change: 1 addition & 0 deletions src/Joystick/Joystick.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "FirmwarePlugin.h"
#include "QGCLoggingCategory.h"
#include "GimbalController.h"
#include "QmlObjectListModel.h"

#include <QtCore/QSettings>

Expand Down
6 changes: 6 additions & 0 deletions src/Joystick/Joystick.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
#include <QtCore/QObject>
#include <QtCore/QThread>
#include <QtCore/QLoggingCategory>
#include <QtQmlIntegration/QtQmlIntegration>

// JoystickLog Category declaration moved to QGCLoggingCategory.cc to allow access in Vehicle
Q_DECLARE_LOGGING_CATEGORY(JoystickValuesLog)
Q_DECLARE_METATYPE(GRIPPER_ACTIONS)

class MultiVehicleManager;
class Vehicle;
class QmlObjectListModel;

/// Action assigned to button
class AssignedButtonAction : public QObject {
Expand Down Expand Up @@ -54,6 +56,10 @@ class AssignableButtonAction : public QObject {
class Joystick : public QThread
{
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("")
Q_MOC_INCLUDE("QmlObjectListModel.h")
Q_MOC_INCLUDE("Vehicle.h")
public:
Joystick(const QString& name, int axisCount, int buttonCount, int hatCount, MultiVehicleManager* multiVehicleManager);

Expand Down
12 changes: 3 additions & 9 deletions src/Joystick/JoystickAndroid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,8 @@ bool JoystickAndroid::_getHat(int hat,int i) {
}
}

static JoystickManager *_manager = nullptr;

//helper method
bool JoystickAndroid::init(JoystickManager *manager) {
_manager = manager;

bool JoystickAndroid::init() {
//this gets list of all possible buttons - this is needed to check how many buttons our gamepad supports
//instead of the whole logic below we could have just a simple array of hardcoded int values as these 'should' not change

Expand Down Expand Up @@ -296,10 +292,8 @@ static void jniUpdateAvailableJoysticks(JNIEnv *envA, jobject thizA)
Q_UNUSED(envA);
Q_UNUSED(thizA);

if (_manager != nullptr) {
qCDebug(JoystickLog) << "jniUpdateAvailableJoysticks triggered";
emit _manager->updateAvailableJoysticksSignal();
}
qCDebug(JoystickLog) << "jniUpdateAvailableJoysticks triggered";
emit JoystickManager::instance()->updateAvailableJoysticksSignal();
}

void JoystickAndroid::setNativeMethods()
Expand Down
4 changes: 1 addition & 3 deletions src/Joystick/JoystickAndroid.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,14 @@
#include <QtCore/private/qandroidextras_p.h>

class MultiVehicleManager;
class JoystickManager;

class JoystickAndroid : public Joystick, public QtAndroidPrivate::GenericMotionEventListener, public QtAndroidPrivate::KeyEventListener
{
public:
JoystickAndroid(const QString& name, int axisCount, int buttonCount, int id, MultiVehicleManager* multiVehicleManager);

~JoystickAndroid();

static bool init(JoystickManager *manager);
static bool init();

static void setNativeMethods();

Expand Down
127 changes: 57 additions & 70 deletions src/Joystick/JoystickManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,80 +7,82 @@
*
****************************************************************************/


#include "JoystickManager.h"
#include "MultiVehicleManager.h"
#include "Joystick.h"
#if defined(QGC_SDL_JOYSTICK)
#include "JoystickSDL.h"
#elif defined(Q_OS_ANDROID)
#include "JoystickAndroid.h"
#endif
#include "QGCApplication.h"
#include "MultiVehicleManager.h"
#include "QGCLoggingCategory.h"

#include <QtCore/qapplicationstatic.h>
#include <QtCore/QSettings>
#include <QtCore/QTimer>
#include <QtQml/QQmlEngine>
#include <QtQml/QtQml>

QGC_LOGGING_CATEGORY(JoystickManagerLog, "JoystickManagerLog")
QGC_LOGGING_CATEGORY(JoystickManagerLog, "qgc.joystick.joystickmanager")

JoystickManager::JoystickManager(QGCApplication* app, QGCToolbox* toolbox)
: QGCTool(app, toolbox)
, _activeJoystick(nullptr)
, _multiVehicleManager(nullptr)
Q_APPLICATION_STATIC(JoystickManager, _joystickManager);

JoystickManager::JoystickManager(QObject *parent)
: QObject(parent)
, _joystickCheckTimer(new QTimer(this))
{
// qCDebug(JoystickManagerLog) << Q_FUNC_INFO << this;

_joystickCheckTimer->setInterval(1000);
_joystickCheckTimer->setSingleShot(false);
}

JoystickManager::~JoystickManager()
{
QMap<QString, Joystick*>::iterator i;
for (i = _name2JoystickMap.begin(); i != _name2JoystickMap.end(); ++i) {
qCDebug(JoystickManagerLog) << "Releasing joystick:" << i.key();
i.value()->stop();
delete i.value();
for (QMap<QString, Joystick*>::key_value_iterator it = _name2JoystickMap.keyValueBegin(); it != _name2JoystickMap.keyValueEnd(); ++it) {
qCDebug(JoystickManagerLog) << "Releasing joystick:" << it->first;
it->second->stop();
delete it->second;
}

// qCDebug(JoystickManagerLog) << Q_FUNC_INFO << this;
}

void JoystickManager::setToolbox(QGCToolbox *toolbox)
JoystickManager *JoystickManager::instance()
{
QGCTool::setToolbox(toolbox);

_multiVehicleManager = _toolbox->multiVehicleManager();

QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
qmlRegisterUncreatableType<JoystickManager>("QGroundControl.JoystickManager", 1, 0, "JoystickManager", "Reference only");
qmlRegisterUncreatableType<Joystick> ("QGroundControl.JoystickManager", 1, 0, "Joystick", "Reference only");
return _joystickManager();
}

void JoystickManager::init() {
void JoystickManager::init()
{
#ifdef QGC_SDL_JOYSTICK
if (!JoystickSDL::init()) {
return;
}
_setActiveJoystickFromSettings();
#elif defined(Q_OS_ANDROID)
if (!JoystickAndroid::init(this)) {
if (!JoystickAndroid::init()) {
return;
}
connect(this, &JoystickManager::updateAvailableJoysticksSignal, this, &JoystickManager::restartJoystickCheckTimer);
(void) connect(this, &JoystickManager::updateAvailableJoysticksSignal, this, [this]() {
_joystickCheckTimerCounter = 5;
_joystickCheckTimer->start();
});
#endif
connect(&_joystickCheckTimer, &QTimer::timeout, this, &JoystickManager::_updateAvailableJoysticks);
(void) connect(_joystickCheckTimer, &QTimer::timeout, this, &JoystickManager::_updateAvailableJoysticks);
_joystickCheckTimerCounter = 5;
_joystickCheckTimer.start(1000);
_joystickCheckTimer->start();
}

void JoystickManager::_setActiveJoystickFromSettings(void)
void JoystickManager::_setActiveJoystickFromSettings()
{
QMap<QString,Joystick*> newMap;

#ifdef QGC_SDL_JOYSTICK
// Get the latest joystick mapping
newMap = JoystickSDL::discover(_multiVehicleManager);
newMap = JoystickSDL::discover(qgcApp()->toolbox()->multiVehicleManager());
#elif defined(Q_OS_ANDROID)
newMap = JoystickAndroid::discover(_multiVehicleManager);
newMap = JoystickAndroid::discover(qgcApp()->toolbox()->multiVehicleManager());
#endif

if (_activeJoystick && !newMap.contains(_activeJoystick->name())) {
Expand All @@ -90,47 +92,45 @@ void JoystickManager::_setActiveJoystickFromSettings(void)

// Check to see if our current mapping contains any joysticks that are not in the new mapping
// If so, those joysticks have been unplugged, and need to be cleaned up
QMap<QString, Joystick*>::iterator i;
for (i = _name2JoystickMap.begin(); i != _name2JoystickMap.end(); ++i) {
if (!newMap.contains(i.key())) {
qCDebug(JoystickManagerLog) << "Releasing joystick:" << i.key();
i.value()->stopPolling();
i.value()->wait(1000);
i.value()->deleteLater();
for (QMap<QString, Joystick*>::key_value_iterator it = _name2JoystickMap.keyValueBegin(); it != _name2JoystickMap.keyValueEnd(); ++it) {
if (!newMap.contains(it->first)) {
qCDebug(JoystickManagerLog) << "Releasing joystick:" << it->first;
it->second->stopPolling();
it->second->wait(1000);
it->second->deleteLater();
}
}

_name2JoystickMap = newMap;
emit availableJoysticksChanged();

if (!_name2JoystickMap.count()) {
if (_name2JoystickMap.isEmpty()) {
setActiveJoystick(nullptr);
return;
}

QSettings settings;

settings.beginGroup(_settingsGroup);
QString name = settings.value(_settingsKeyActiveJoystick).toString();

QString name = settings.value(_settingsKeyActiveJoystick).toString();
if (name.isEmpty()) {
name = _name2JoystickMap.first()->name();
}

setActiveJoystick(_name2JoystickMap.value(name, _name2JoystickMap.first()));
settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name());

settings.endGroup();
}

Joystick* JoystickManager::activeJoystick(void)
Joystick *JoystickManager::activeJoystick()
{
return _activeJoystick;
}

void JoystickManager::setActiveJoystick(Joystick* joystick)
void JoystickManager::setActiveJoystick(Joystick *joystick)
{
QSettings settings;

if (joystick != nullptr && !_name2JoystickMap.contains(joystick->name())) {
if (joystick && !_name2JoystickMap.contains(joystick->name())) {
qCWarning(JoystickManagerLog) << "Set active not in map" << joystick->name();
return;
}
Expand All @@ -148,49 +148,42 @@ void JoystickManager::setActiveJoystick(Joystick* joystick)
if (_activeJoystick != nullptr) {
qCDebug(JoystickManagerLog) << "Set active:" << _activeJoystick->name();

QSettings settings;
settings.beginGroup(_settingsGroup);
settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name());
settings.endGroup();
}

emit activeJoystickChanged(_activeJoystick);
emit activeJoystickNameChanged(_activeJoystick?_activeJoystick->name():"");
emit activeJoystickNameChanged(_activeJoystick ? _activeJoystick->name() : "");
}

QVariantList JoystickManager::joysticks(void)
QVariantList JoystickManager::joysticks()
{
QVariantList list;

for (const QString &name: _name2JoystickMap.keys()) {
list += QVariant::fromValue(_name2JoystickMap[name]);
for (auto it = _name2JoystickMap.constBegin(); it != _name2JoystickMap.constEnd(); ++it) {
list += QVariant::fromValue(it.value());
}

return list;
}

QStringList JoystickManager::joystickNames(void)
{
return _name2JoystickMap.keys();
}

QString JoystickManager::activeJoystickName(void)
QString JoystickManager::activeJoystickName() const
{
return _activeJoystick ? _activeJoystick->name() : QString();
return (_activeJoystick ? _activeJoystick->name() : QString());
}

bool JoystickManager::setActiveJoystickName(const QString& name)
bool JoystickManager::setActiveJoystickName(const QString &name)
{
if (_name2JoystickMap.contains(name)) {
setActiveJoystick(_name2JoystickMap[name]);
return true;
} else {
qCWarning(JoystickManagerLog) << "Set active not in map" << name;
return false;
}

qCWarning(JoystickManagerLog) << "Set active not in map" << name;
return false;
}

/*
* TODO: move this to the right place: JoystickSDL.cc and JoystickAndroid.cc respectively and call through Joystick.cc
*/
void JoystickManager::_updateAvailableJoysticks()
{
#ifdef QGC_SDL_JOYSTICK
Expand All @@ -216,13 +209,7 @@ void JoystickManager::_updateAvailableJoysticks()
_joystickCheckTimerCounter--;
_setActiveJoystickFromSettings();
if (_joystickCheckTimerCounter <= 0) {
_joystickCheckTimer.stop();
_joystickCheckTimer->stop();
}
#endif
}

void JoystickManager::restartJoystickCheckTimer()
{
_joystickCheckTimerCounter = 5;
_joystickCheckTimer.start(1000);
}
Loading

0 comments on commit 78f8fca

Please sign in to comment.