From 9a18ef852beee37ecf073718fbb527c89cb70337 Mon Sep 17 00:00:00 2001 From: ChenZhuo Date: Thu, 3 Apr 2025 16:30:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9B=BE=E9=A9=AC=E6=96=AF?= =?UTF-8?q?=E7=89=B9=E6=91=87=E6=9D=86=E6=8E=A7=E5=88=B6=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=EF=BC=8C=E6=8C=89=E9=92=AE=E6=9C=AA=E5=85=B3?= =?UTF-8?q?=E8=81=94=E5=90=8A=E8=88=B1=E6=8E=A7=E5=88=B6=E9=94=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CMakeLists.txt | 9 ++ src/commandwidget.cpp | 66 +++++++++++++++ src/commandwidget.h | 6 ++ src/directinputjoystick.cpp | 164 ++++++++++++++++++++++++++++++++++++ src/directinputjoystick.h | 47 +++++++++++ src/joystickcontroller.cpp | 106 +++++++++++++++++++++++ src/joystickcontroller.h | 41 +++++++++ src/mainwindow.cpp | 37 ++++++++ src/mainwindow.h | 15 +++- src/video/readstream.cpp | 1 + src/video/readstream.h | 1 - 11 files changed, 491 insertions(+), 2 deletions(-) create mode 100644 src/directinputjoystick.cpp create mode 100644 src/directinputjoystick.h create mode 100644 src/joystickcontroller.cpp create mode 100644 src/joystickcontroller.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ef4ecb7..cce6152 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,9 +13,14 @@ qt_add_executable(VideoClient videoControl.h videoControl.ui videoControl.cpp wprogressbar.h wprogressbar.cpp webmapwidget.h webmapwidget.cpp + joystickcontroller.h joystickcontroller.cpp + directinputjoystick.h directinputjoystick.cpp + ) + + qt6_add_resources(VideoClient "resources" PREFIX "/" FILES "resources/res.qrc" @@ -39,7 +44,11 @@ target_link_libraries(VideoClient Qt6::Network Qt6::SerialPort Qt6::WebEngineWidgets + #Qt6::Gamepad video + winmm + dinput8 + dxguid # QWindowKit::Widgets # WidgetFrame ) diff --git a/src/commandwidget.cpp b/src/commandwidget.cpp index 829c58b..7138715 100644 --- a/src/commandwidget.cpp +++ b/src/commandwidget.cpp @@ -145,3 +145,69 @@ void CommandWidget::on_pushButton_16_clicked() { void CommandWidget::on_pushButton_15_clicked() { buttonResponse(0xC9); } + + +void CommandWidget::onButtonChanged(int button, bool pressed) +{ + qDebug() << "Button" << button << (pressed ? "Pressed" : "Released"); + // switch (button) + // { + // case 0: + // on_pushButton_clicked(); + // break; + // case 1: + // on_pushButton_2_clicked(); + // break; + // case 2: + // on_pushButton_3_clicked(); + // break; + // case 3: + // on_pushButton_clicked(); + // break; + // case 4: + // on_pushButton_2_clicked(); + // break; + // case 5: + // on_pushButton_3_clicked(); + // break; + // case 6: + // on_pushButton_clicked(); + // break; + // case 7: + // on_pushButton_2_clicked(); + // break; + // case 8: + // on_pushButton_3_clicked(); + // break; + // case 9: + // on_pushButton_clicked(); + // break; + // case 10: + // on_pushButton_2_clicked(); + // break; + // case 11: + // on_pushButton_3_clicked(); + // break; + // case 12: + // on_pushButton_clicked(); + // break; + // case 13: + // on_pushButton_2_clicked(); + // break; + // case 14: + // on_pushButton_3_clicked(); + // break; + + // } + +} + + +void CommandWidget::onDirectionChanged(int direction){ + + direction!=42949672?qDebug() << "direction" << direction:qDebug() << "center"; + + +} + + diff --git a/src/commandwidget.h b/src/commandwidget.h index f042863..17a4a4c 100644 --- a/src/commandwidget.h +++ b/src/commandwidget.h @@ -122,6 +122,12 @@ private slots: void on_pushButton_15_clicked(); +public slots: + + void onButtonChanged(int button, bool pressed); + void onDirectionChanged(int dirction); + + private: Ui::CommandWidget *ui; QUdpSocket *m_commandUdpSocket = nullptr; diff --git a/src/directinputjoystick.cpp b/src/directinputjoystick.cpp new file mode 100644 index 0000000..c90f49b --- /dev/null +++ b/src/directinputjoystick.cpp @@ -0,0 +1,164 @@ +#include "DirectInputJoystick.h" +#include + +DirectInputJoystick::DirectInputJoystick(QObject *parent) : QObject(parent) { + // 确保 COM 库在主线程初始化 + CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); +} + +DirectInputJoystick::~DirectInputJoystick() { + cleanup(); + CoUninitialize(); +} + +bool DirectInputJoystick::initialize() { + HRESULT hr = DirectInput8Create( + GetModuleHandle(nullptr), + DIRECTINPUT_VERSION, + IID_IDirectInput8, + (VOID**)&m_pDirectInput, + nullptr + ); + + if (FAILED(hr)) { + emit errorOccurred("无法创建 DirectInput 对象"); + return false; + } + + // 枚举所有摇杆设备 + hr = m_pDirectInput->EnumDevices( + DI8DEVCLASS_GAMECTRL, + enumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY + ); + + return SUCCEEDED(hr); +} + +BOOL CALLBACK DirectInputJoystick::enumJoysticksCallback(const DIDEVICEINSTANCE* instance, VOID* context) { + DirectInputJoystick* joystick = static_cast(context); + return joystick->setupDevice(); +} + +bool DirectInputJoystick::setupDevice() { + if (!m_pDirectInput) return false; + + // 创建设备 + HRESULT hr = m_pDirectInput->CreateDevice( + GUID_Joystick, + &m_pJoystick, + nullptr + ); + + if (FAILED(hr)) { + emit errorOccurred("无法创建摇杆设备"); + return false; + } + + // 设置数据格式 + hr = m_pJoystick->SetDataFormat(&c_dfDIJoystick); + if (FAILED(hr)) { + emit errorOccurred("设置数据格式失败"); + return false; + } + + // 设置协作级别 + hr = m_pJoystick->SetCooperativeLevel( + nullptr, // 无窗口句柄 + DISCL_BACKGROUND | DISCL_NONEXCLUSIVE + ); + + // 枚举轴并设置范围 + hr = m_pJoystick->EnumObjects(enumAxesCallback, this, DIDFT_AXIS); + if (FAILED(hr)) { + emit errorOccurred("枚举摇杆轴失败"); + return false; + } + + // 创建事件对象 + m_hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + hr = m_pJoystick->SetEventNotification(m_hEvent); + if (FAILED(hr)) { + emit errorOccurred("设置事件通知失败"); + return false; + } + + return true; +} + +BOOL CALLBACK DirectInputJoystick::enumAxesCallback(const DIDEVICEOBJECTINSTANCE* doi, VOID* context) { + DirectInputJoystick* joystick = static_cast(context); + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = doi->dwType; + diprg.lMin = -1000; + diprg.lMax = 1000; + + HRESULT hr = joystick->m_pJoystick->SetProperty(DIPROP_RANGE, &diprg.diph); + return SUCCEEDED(hr); +} + +void DirectInputJoystick::startListening() { + if (!m_pJoystick || m_isRunning) return; + + m_isRunning = true; + m_workerThread = QThread::create([this]() { + m_pJoystick->Acquire(); + + while (m_isRunning) { + WaitForSingleObject(m_hEvent, INFINITE); + + DIJOYSTATE state; + HRESULT hr = m_pJoystick->GetDeviceState(sizeof(DIJOYSTATE), &state); + if (SUCCEEDED(hr)) { + // 处理轴数据 + double x = state.lX / 1000.0; + double y = state.lY / 1000.0; + double z = state.lZ / 1000.0; + emit axisChanged(0, x); + emit axisChanged(1, y); + emit axisChanged(2, z); + + // 处理按钮 + for (int i = 0; i < 32; ++i) { + if(lastState.rgbButtons[i]!=state.rgbButtons[i]) + { + bool pressed = (state.rgbButtons[i] & 0x80) != 0; + + emit buttonChanged(i, pressed); + } + + } + if(lastState.rgdwPOV[0]!=state.rgdwPOV[0]) + { + emit directionChanged(state.rgdwPOV[0]/100); + + } + } + lastState = state; + } + }); + + connect(m_workerThread, &QThread::finished, m_workerThread, &QThread::deleteLater); + m_workerThread->start(); +} + +void DirectInputJoystick::cleanup() { + m_isRunning = false; + if (m_hEvent) { + CloseHandle(m_hEvent); + m_hEvent = nullptr; + } + if (m_pJoystick) { + m_pJoystick->Unacquire(); + m_pJoystick->Release(); + m_pJoystick = nullptr; + } + if (m_pDirectInput) { + m_pDirectInput->Release(); + m_pDirectInput = nullptr; + } +} diff --git a/src/directinputjoystick.h b/src/directinputjoystick.h new file mode 100644 index 0000000..d85bdc1 --- /dev/null +++ b/src/directinputjoystick.h @@ -0,0 +1,47 @@ +#ifndef DIRECTINPUTJOYSTICK_H +#define DIRECTINPUTJOYSTICK_H + +#include +#include +#include +#include + + +class DirectInputJoystick : public QObject +{ + Q_OBJECT +public: + explicit DirectInputJoystick(QObject *parent = nullptr); + ~DirectInputJoystick(); + + + bool initialize(); + void startListening(); + + +signals: + // 轴变化信号(axis: 0-X, 1-Y, 2-Z; value: -1.0 ~ 1.0) + void axisChanged(int axis, double value); + // 按钮状态变化(button: 按钮编号,从0开始;pressed: 是否按下) + void buttonChanged(int button, bool pressed); + // 方向按钮状态变化(direction: 按钮编号,上下左右;pressed: 是否按下) + void directionChanged(int direction); + // 错误信号 + void errorOccurred(const QString &message); + + +private: + bool setupDevice(); + void cleanup(); + static BOOL CALLBACK enumAxesCallback(const DIDEVICEOBJECTINSTANCE* doi, VOID* context); + static BOOL CALLBACK enumJoysticksCallback(const DIDEVICEINSTANCE* instance, VOID* context); + + DIJOYSTATE lastState; + LPDIRECTINPUT8 m_pDirectInput = nullptr; + LPDIRECTINPUTDEVICE8 m_pJoystick = nullptr; + HANDLE m_hEvent = nullptr; + QThread *m_workerThread; + bool m_isRunning = false; +}; + +#endif // DIRECTINPUTJOYSTICK_H diff --git a/src/joystickcontroller.cpp b/src/joystickcontroller.cpp new file mode 100644 index 0000000..039dacf --- /dev/null +++ b/src/joystickcontroller.cpp @@ -0,0 +1,106 @@ +#include "joystickcontroller.h" +#include + + + + +JoystickController::JoystickController(int joystickId, QObject *parent) + : QObject{parent}, m_joystickId(joystickId), m_isConnected(false) +{ + + // 初始化定时器 + m_timer = new QTimer(this); + connect(m_timer, &QTimer::timeout, this, &JoystickController::pollJoystick); + + // 检测设备是否存在 + UINT numDevs = joyGetNumDevs(); + if (numDevs == 0) { + emit errorOccurred("系统未检测到任何摇杆设备"); + return; + } + // 获取设备能力 + MMRESULT capsResult = joyGetDevCaps(m_joystickId, &m_joyCaps, sizeof(JOYCAPS)); + if (capsResult != JOYERR_NOERROR) { + emit errorOccurred(QString("无法获取摇杆设备能力,错误代码: %1").arg(capsResult)); + return; + } + + + m_isConnected = true; + qDebug() << "摇杆设备初始化成功,名称:" << QString::fromWCharArray(m_joyCaps.szPname); + + + +} + + +JoystickController::~JoystickController() +{ + stopPolling(); +} + + + +bool JoystickController::isConnected() const +{ + return m_isConnected; +} + + +void JoystickController::startPolling(int intervalMs) +{ + if (m_isConnected) { + m_timer->start(intervalMs); + } +} + +void JoystickController::stopPolling() +{ + m_timer->stop(); +} + + +void JoystickController::pollJoystick() +{ + JOYINFOEX joyInfo; + joyInfo.dwSize = sizeof(JOYINFOEX); + joyInfo.dwFlags = JOY_RETURNALL; + + MMRESULT result = joyGetPosEx(m_joystickId, &joyInfo); + if (result != JOYERR_NOERROR) { + emit errorOccurred(QString("读取摇杆数据失败,错误代码: %1").arg(result)); + m_isConnected = false; + stopPolling(); + return; + } + + // 处理轴数据 + normalizeAxisValues(joyInfo); + + // 处理按钮状态 + for (int i = 0; i < m_joyCaps.wNumButtons; ++i) { + bool isPressed = (joyInfo.dwButtons & (1 << i)) != 0; + emit buttonChanged(i + 1, isPressed); // 按钮ID从1开始 + } + +} + + +void JoystickController::normalizeAxisValues(const JOYINFOEX &joyInfo) +{ + // X/Y轴归一化处理 + double x = (joyInfo.dwXpos - 32768) / 32768.0; + double y = (joyInfo.dwYpos - 32768) / 32768.0; + emit axisChanged(1, x); // 假设轴1为X轴 + emit axisChanged(2, y); // 轴2为Y轴 + + // 其他轴(如Z轴、Rudder等) + if (m_joyCaps.wCaps & JOYCAPS_HASZ) { + double z = (joyInfo.dwZpos - 32768) / 32768.0; + emit axisChanged(3, z); + } +} + + + + diff --git a/src/joystickcontroller.h b/src/joystickcontroller.h new file mode 100644 index 0000000..f43dc88 --- /dev/null +++ b/src/joystickcontroller.h @@ -0,0 +1,41 @@ +#ifndef JOYSTICKCONTROLLER_H +#define JOYSTICKCONTROLLER_H + +#include +#include +#include +#include + +class JoystickController : public QObject +{ + Q_OBJECT +public: + explicit JoystickController(int joystickId = JOYSTICKID1, QObject *parent = nullptr); + ~JoystickController(); + + bool isConnected() const; + void startPolling(int intervalMs = 50); + void stopPolling(); + + +signals: + // 摇杆轴变化信号(范围:-1.0 ~ 1.0) + void axisChanged(int axis, double value); + // 按钮状态变化信号(按钮ID, 是否按下) + void buttonChanged(int button, bool pressed); + // 错误信号 + void errorOccurred(const QString &message); + + +private slots: + void pollJoystick(); +private: + void normalizeAxisValues(const JOYINFOEX &joyInfo); + + QTimer *m_timer; + int m_joystickId; + bool m_isConnected; + JOYCAPS m_joyCaps; +}; + +#endif // JOYSTICKCONTROLLER_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5f2a291..7d37689 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -32,6 +32,7 @@ MainWindow::MainWindow(QWidget *parent) qDebug() << "Open file fail " << Qt::endl; } + // QList list; // list.append("rtmp://liteavapp.qcloud.com/live/liteavdemoplayerstreamid"); // list.append("rtsp://182.92.130.23/nmyj/video"); @@ -60,6 +61,8 @@ MainWindow::MainWindow(QWidget *parent) initHideButton(); + //initJoyStick(); + initDtJoyStick(); setSavedVideoDir(); // ui->stackedWidget->setCurrentIndex(1); // ui->videoWidget1->play(list.at(0)); @@ -123,6 +126,8 @@ void MainWindow::initSignalConnection() { connect(ui->videoControlWidget, &VideoControl::stopVideoSignal, this, &MainWindow::closeVideoSlot); + + } void MainWindow::initNotifyMessageConnection() { @@ -141,6 +146,38 @@ void MainWindow::initChangeVideoLayoutConnection() { }); } + + +void MainWindow::onAxisChanged(int axis, double value) +{ + qDebug() << "Axis" << axis << "Value:" << value; +} + + + + +// void MainWindow::initJoyStick() +// { +// m_joystick = new JoystickController(JOYSTICKID1,this); +// connect(m_joystick, &JoystickController::axisChanged, this, &MainWindow::onAxisChanged); +// connect(m_joystick, &JoystickController::buttonChanged, this, &MainWindow::onButtonChanged); +// if (m_joystick->isConnected()) { +// m_joystick->startPolling(); +// } +// } + +void MainWindow::initDtJoyStick() +{ + m_dtjoystick = new DirectInputJoystick(this); + + if (m_dtjoystick->initialize()) { + connect(m_dtjoystick, &DirectInputJoystick::buttonChanged, ui->commandWidget, &CommandWidget::onButtonChanged); + connect(m_dtjoystick, &DirectInputJoystick::directionChanged, ui->commandWidget, &CommandWidget::onDirectionChanged); + // connect(m_dtjoystick, &DirectInputJoystick::buttonChanged, this, &MainWindow::onButtonChanged); + m_dtjoystick->startListening(); + } +} + void MainWindow::initNotifyManager() { m_notifyManager = new NotifyManager(this, this); m_notifyManager->setMaxCount(5); diff --git a/src/mainwindow.h b/src/mainwindow.h index 0412624..3355d85 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -16,7 +16,9 @@ #include "videoControl.h" #include "videowidget.h" #include "webmapwidget.h" - +//#include "joystickapi.h" +#include "joystickcontroller.h" +#include "DirectInputJoystick.h" #ifdef Q_OS_WIN #include "windows.h" #include "windowsx.h" @@ -68,6 +70,14 @@ private: void setSavedVideoDir(); void initHideButton(); + // void initJoyStick(); + void initDtJoyStick(); + + +private slots: + + void onAxisChanged(int axis, double value); + private slots: void showSettingDlgSlot(); @@ -92,5 +102,8 @@ private: QToolButton *hideCommandWidgetBtn = nullptr; WebMapWidget *m_mapWidget = nullptr; + // JoystickController *m_joystick = nullptr; + DirectInputJoystick *m_dtjoystick; + }; #endif // MAINWINDOW_H diff --git a/src/video/readstream.cpp b/src/video/readstream.cpp index 9a3162f..d58a47e 100644 --- a/src/video/readstream.cpp +++ b/src/video/readstream.cpp @@ -200,6 +200,7 @@ bool ReadStream::initSocket(QString ip, int port) { } } } + } bool ReadStream::initSavedRawFile(QString fileDir, QString uavName) { diff --git a/src/video/readstream.h b/src/video/readstream.h index dd4a465..5155316 100644 --- a/src/video/readstream.h +++ b/src/video/readstream.h @@ -12,7 +12,6 @@ #include "avpacketqueuemanager.h" #include "decodestream.h" -#include "ffmpeginclude.h" #include "pushstream.h" #include "savestream.h"