/* SPDX-FileCopyrightText: 2024 Arthur Kasimov SPDX-License-Identifier: GPL-2.0-or-later */ #include "device.h" #include "logging.h" Device::Device(int deviceIndex, QObject *parent) : QObject(parent) , m_deviceIndex(deviceIndex) { } Device::~Device() { close(); } bool Device::open() { if (m_joystick != nullptr) { return true; } m_joystick = SDL_JoystickOpen(m_deviceIndex); m_controller = SDL_GameControllerOpen(m_deviceIndex); if (!m_controller) { m_leftTrigger = SDL_JoystickGetAxis(m_joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT); m_rightTrigger = SDL_JoystickGetAxis(m_joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); qCDebug(KCM_GAMECONTROLLER) << "Device" << m_deviceIndex << "is not a gamepad. using as joystick"; } else { m_leftTrigger = SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT); m_rightTrigger = SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); } return m_joystick != nullptr; } void Device::close() { if (m_joystick == nullptr) { return; } if (m_controller) { SDL_GameControllerClose(m_controller); m_controller = nullptr; } SDL_JoystickClose(m_joystick); m_joystick = nullptr; } bool Device::isController() const { return m_controller != nullptr; } SDL_JoystickID Device::id() const { return SDL_JoystickInstanceID(m_joystick); } QString Device::name() const { return QString::fromLocal8Bit(SDL_JoystickName(m_joystick)); } QString Device::path() const { return QString::fromLocal8Bit(SDL_JoystickPath(m_joystick)); } bool Device::isVirtual() const { return SDL_JoystickIsVirtual(m_deviceIndex); } int Device::buttonCount() const { return SDL_JoystickNumButtons(m_joystick); } bool Device::buttonState(int index) const { // If we are a game controller, use that api to get button state if (m_controller) { return SDL_GameControllerGetButton(m_controller, static_cast(index)) != 0; } return SDL_JoystickGetButton(m_joystick, index) != 0; } int Device::axisCount() const { return SDL_JoystickNumAxes(m_joystick); } QVector2D Device::leftAxisValue() const { return m_leftAxis; } QVector2D Device::rightAxisValue() const { return m_rightAxis; } float Device::leftTriggerValue() const { return m_leftTrigger; } float Device::rightTriggerValue() const { return m_rightTrigger; } int Device::hatCount() const { return SDL_JoystickNumHats(m_joystick); } QVector2D Device::hatPosition(int index) const { const Uint8 hat = SDL_JoystickGetHat(m_joystick, index); QVector2D position; if ((hat & SDL_HAT_LEFT) != 0) { position.setX(std::numeric_limits::min()); } else if ((hat & SDL_HAT_RIGHT) != 0) { position.setX(std::numeric_limits::max()); } if ((hat & SDL_HAT_UP) != 0) { position.setY(std::numeric_limits::min()); } else if ((hat & SDL_HAT_DOWN) != 0) { position.setY(std::numeric_limits::max()); } return position; } void Device::onButtonEvent(const SDL_JoyButtonEvent &event) { Q_EMIT buttonStateChanged(event.button); } void Device::onControllerButtonEvent(const SDL_ControllerButtonEvent &event) { Q_EMIT buttonStateChanged(event.button); } void Device::onAxisEvent(const SDL_JoyAxisEvent &event) { const float value = static_cast(event.value) / std::numeric_limits::max(); if (event.axis == SDL_CONTROLLER_AXIS_LEFTX) { m_leftAxis.setX(value); Q_EMIT leftAxisChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_LEFTY) { m_leftAxis.setY(value); Q_EMIT leftAxisChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_RIGHTX) { m_rightAxis.setX(value); Q_EMIT rightAxisChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_RIGHTY) { m_rightAxis.setY(value); Q_EMIT rightAxisChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT) { m_leftTrigger = value; Q_EMIT leftTriggerChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) { m_rightTrigger = value; Q_EMIT rightTriggerChanged(); } } void Device::onControllerAxisEvent(const SDL_ControllerAxisEvent &event) { const float value = static_cast(event.value) / std::numeric_limits::max(); if (event.axis == SDL_CONTROLLER_AXIS_LEFTX) { m_leftAxis.setX(value); Q_EMIT leftAxisChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_LEFTY) { m_leftAxis.setY(value); Q_EMIT leftAxisChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_RIGHTX) { m_rightAxis.setX(value); Q_EMIT rightAxisChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_RIGHTY) { m_rightAxis.setY(value); Q_EMIT rightAxisChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT) { m_leftTrigger = value; Q_EMIT leftTriggerChanged(); } else if (event.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) { m_rightTrigger = value; Q_EMIT rightTriggerChanged(); } } void Device::onHatEvent(const SDL_JoyHatEvent &event) { Q_EMIT hatPositionChanged(event.hat); } #include "moc_device.cpp"