玉兔远程控制 0.1.0-bate5
载入中...
搜索中...
未找到
BackendDesktop.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QApplication>
4#include <QClipboard>
5#include <QWheelEvent>
6#include <QVideoFrame>
7#include <QDesktopServices>
8#include <QLoggingCategory>
9#include <QFileInfo>
10
11#include "BackendDesktop.h"
12#include "FrmScroll.h"
13
14static Q_LOGGING_CATEGORY(log, "Backend.Desktop")
15static Q_LOGGING_CATEGORY(logMouse, "Backend.Desktop.Mouse")
16
17#define TypeRecordVideo (QEvent::User + 1)
18class QRecordVideoEvent : public QEvent
19{
20public:
21 QRecordVideoEvent(const QImage& img): QEvent((QEvent::Type)TypeRecordVideo)
22 {
23 m_Image = img;
24 }
26 {
27 //qDebug(log) << Q_FUNC_INFO;
28 }
29
30 QImage GetImage()
31 {
32 return m_Image;
33 }
34private:
35 QImage m_Image;
36};
37
38int g_QtKeyboardModifiers = qRegisterMetaType<Qt::KeyboardModifiers>("KeyboardModifiers");
39int g_QtMouseButtons = qRegisterMetaType<Qt::MouseButtons>("MouseButtons");
40int g_QtMouseButton = qRegisterMetaType<Qt::MouseButton>("MouseButton");
41int g_QMessageBox_Icon = qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
42
43CBackendDesktop::CBackendDesktop(COperateDesktop *pOperate)
44 : CBackend(pOperate)
45#if HAVE_QT6_RECORD
46 , m_pParameterRecord(nullptr)
47 , m_VideoFrameInput(this)
48 , m_AudioBufferInput(this)
49 , m_AudioBufferOutput(this)
50#endif
51{
52 qDebug(log) << Q_FUNC_INFO;
53 if(pOperate) {
54 CFrmScroll* pScroll = qobject_cast<CFrmScroll*>(pOperate->GetViewer());
55 if(pScroll) {
56 CFrmViewer* pView = pScroll->GetViewer();
57 if(pView)
58 SetViewer(pView);
59 else {
60 QString szErr = pOperate->metaObject()->className();
61 szErr += "::GetViewer() is not CFrmViewer";
62 qWarning(log) << szErr.toStdString().c_str();
63 }
64 } else {
65 QString szErr = pOperate->metaObject()->className();
66 szErr += "::GetViewer() is not CFrmScroll";
67 qWarning(log) << szErr.toStdString().c_str();
68 }
69 SetConnect(pOperate);
70 }
71
72#if HAVE_QT6_RECORD
73 bool check = connect(
74 &m_Recorder, &QMediaRecorder::errorOccurred,
75 this, [&](QMediaRecorder::Error error, const QString &errorString) {
76 qDebug(log) << "Recorder error occurred:" << error << errorString;
77 slotRecord(false);
78 emit sigError(error, errorString);
79 });
80 Q_ASSERT(check);
81 check = connect(
82 &m_Recorder, &QMediaRecorder::recorderStateChanged,
83 this, [&](QMediaRecorder::RecorderState state){
84 qDebug(log) << "Recorder state changed:" << state;
85 if(QMediaRecorder::StoppedState == state)
86 {
87 slotRecord(false);
88 if(m_pParameterRecord) {
89 qDebug(log) << "End action:"
90 << m_pParameterRecord->GetEndAction()
91 << m_Recorder.actualLocation();
92 switch(m_pParameterRecord->GetEndAction())
93 {
94 case CParameterRecord::ENDACTION::OpenFile:
95 QDesktopServices::openUrl(m_Recorder.actualLocation());
96 break;
97 case CParameterRecord::ENDACTION::OpenFolder: {
98 QFileInfo fi(m_Recorder.actualLocation().toLocalFile());
99 QDesktopServices::openUrl(
100 QUrl::fromLocalFile(fi.absolutePath()));
101 break;
102 }
103 default:
104 break;
105 }
106 }
107 }
108 });
109 Q_ASSERT(check);
110 check = connect(&m_Recorder, &QMediaRecorder::actualLocationChanged,
111 this, [&](const QUrl &location){
112 qInfo(log) << "Recorder actual location changed:" << location;
113 });
114 Q_ASSERT(check);
115#endif
116}
117
118CBackendDesktop::~CBackendDesktop()
119{
120 qDebug(log) << Q_FUNC_INFO;
121}
122
123int CBackendDesktop::SetConnect(COperateDesktop *pOperate)
124{
125 //qDebug(log) << "CBackendDesktop::SetConnect:" << pOperate;
126 Q_ASSERT(pOperate);
127 if(!pOperate) return -1;
128
129 bool check = false;
130 check = connect(this, SIGNAL(sigServerName(const QString&)),
131 pOperate, SLOT(slotSetServerName(const QString&)));
132 Q_ASSERT(check);
133 check = connect(pOperate, SIGNAL(sigClipBoardChanged()),
134 this, SLOT(slotClipBoardChanged()));
135 Q_ASSERT(check);
136 check = connect(this, SIGNAL(sigSetClipboard(QMimeData*)),
137 pOperate, SLOT(slotSetClipboard(QMimeData*)));
138 Q_ASSERT(check);
139#if HAVE_QT6_RECORD
140 if(pOperate) {
141 m_pParameterRecord = &pOperate->GetParameter()->m_Record;
142 check = connect(pOperate, SIGNAL(sigRecord(bool)),
143 this, SLOT(slotRecord(bool)));
144 Q_ASSERT(check);
145
146 check = connect(pOperate, SIGNAL(sigRecordPause(bool)),
147 this, SLOT(slotRecordPause(bool)));
148 Q_ASSERT(check);
149 check = connect(
150 &m_Recorder,
151 SIGNAL(recorderStateChanged(QMediaRecorder::RecorderState)),
152 pOperate, SLOT(slotRecorderStateChanged(QMediaRecorder::RecorderState)));
153 Q_ASSERT(check);
154 }
155#endif
156 return 0;
157}
158
160{
161 Q_ASSERT(pView);
162 if(!pView) return -1;
163
164 bool check = false;
165 check = connect(this, SIGNAL(sigRunning()), pView, SLOT(slotRunning()));
166 Q_ASSERT(check);
167 check = connect(this, SIGNAL(sigSetDesktopSize(int, int)),
168 pView, SLOT(slotSetDesktopSize(int, int)));
169 Q_ASSERT(check);
170 check = connect(this, SIGNAL(sigServerName(const QString&)),
171 pView, SLOT(slotSetName(const QString&)));
172 Q_ASSERT(check);
173
174 check = connect(this, SIGNAL(sigUpdateRect(const QRect&, const QImage&)),
175 pView, SLOT(slotUpdateRect(const QRect&, const QImage&)));
176 Q_ASSERT(check);
177 check = connect(this, SIGNAL(sigUpdateRect(const QImage&)),
178 pView, SLOT(slotUpdateRect(const QImage&)));
179 Q_ASSERT(check);
180 check = connect(this, SIGNAL(sigUpdateCursor(const QCursor&)),
181 pView, SLOT(slotUpdateCursor(const QCursor&)));
182 Q_ASSERT(check);
183 check = connect(this, SIGNAL(sigUpdateCursorPosition(const QPoint&)),
184 pView, SLOT(slotUpdateCursorPosition(const QPoint&)));
185 Q_ASSERT(check);
186 check = connect(this, SIGNAL(sigUpdateLedState(unsigned int)),
187 pView, SLOT(slotUpdateLedState(unsigned int)));
188 Q_ASSERT(check);
189
190#if HAVE_QT6_RECORD
191 check = connect(this, SIGNAL(sigRecordVideo(bool, qreal)),
192 pView, SLOT(slotRecordVideo(bool, qreal)));
193 Q_ASSERT(check);
194 check = connect(pView, SIGNAL(sigRecordVideo(QImage)),
195 this, SLOT(slotRecordVideo(QImage)),
196 Qt::DirectConnection);
197 Q_ASSERT(check);
198#endif
199
207 check = connect(pView, SIGNAL(sigMousePressEvent(QMouseEvent*, QPoint)),
208 this, SLOT(slotMousePressEvent(QMouseEvent*, QPoint)),
209 Qt::DirectConnection);
210 Q_ASSERT(check);
211 check = connect(pView, SIGNAL(sigMouseReleaseEvent(QMouseEvent*, QPoint)),
212 this, SLOT(slotMouseReleaseEvent(QMouseEvent*, QPoint)),
213 Qt::DirectConnection);
214 Q_ASSERT(check);
215 check = connect(pView, SIGNAL(sigMouseMoveEvent(QMouseEvent*, QPoint)),
216 this, SLOT(slotMouseMoveEvent(QMouseEvent*, QPoint)),
217 Qt::DirectConnection);
218 Q_ASSERT(check);
219 check = connect(pView, SIGNAL(sigWheelEvent(QWheelEvent*, QPoint)),
220 this, SLOT(slotWheelEvent(QWheelEvent*, QPoint)),
221 Qt::DirectConnection);
222 Q_ASSERT(check);
223 check = connect(pView, SIGNAL(sigKeyPressEvent(QKeyEvent*)),
224 this, SLOT(slotKeyPressEvent(QKeyEvent*)),
225 Qt::DirectConnection);
226 Q_ASSERT(check);
227 check = connect(pView, SIGNAL(sigKeyReleaseEvent(QKeyEvent*)),
228 this, SLOT(slotKeyReleaseEvent(QKeyEvent*)),
229 Qt::DirectConnection);
230 Q_ASSERT(check);
231 check = connect(pView, SIGNAL(sigInputMethodEvent(QInputMethodEvent*)),
232 this, SLOT(slotInputMethodEvent(QInputMethodEvent*)),
233 Qt::DirectConnection);
234 Q_ASSERT(check);
235
236 return 0;
237}
238
239void CBackendDesktop::slotWheelEvent(QWheelEvent *event, QPoint pos)
240{
241 QWheelEvent* e = new QWheelEvent(
242 pos,
243#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
244 event->globalPosition(),
245#else
246 event->globalPos(),
247#endif
248 event->pixelDelta(), event->angleDelta(), event->buttons(),
249 event->modifiers(), event->phase(), event->inverted(), event->source());
250 QCoreApplication::postEvent(this, e);
251 WakeUp();
252}
253
254void CBackendDesktop::slotMouseMoveEvent(QMouseEvent *event, QPoint pos)
255{
256#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
257 QMouseEvent* e = new QMouseEvent(event->type(), pos, event->button(),
258 event->buttons(), event->modifiers());
259#else
260 QMouseEvent* e = new QMouseEvent(event->type(), pos, pos, event->button(),
261 event->buttons(), event->modifiers());
262#endif
263 QCoreApplication::postEvent(this, e);
264 WakeUp();
265}
266
267void CBackendDesktop::slotMousePressEvent(QMouseEvent *event, QPoint pos)
268{
269#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
270 QMouseEvent* e = new QMouseEvent(event->type(), pos, event->button(),
271 event->buttons(), event->modifiers());
272#else
273 QMouseEvent* e = new QMouseEvent(event->type(), pos, pos, event->button(),
274 event->buttons(), event->modifiers());
275#endif
276 QCoreApplication::postEvent(this, e);
277 WakeUp();
278}
279
280void CBackendDesktop::slotMouseReleaseEvent(QMouseEvent *event, QPoint pos)
281{
282#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
283 QMouseEvent* e = new QMouseEvent(event->type(), pos, event->button(),
284 event->buttons(), event->modifiers());
285#else
286 QMouseEvent* e = new QMouseEvent(event->type(), pos, pos, event->button(),
287 event->buttons(), event->modifiers());
288#endif
289 QCoreApplication::postEvent(this, e);
290 WakeUp();
291}
292
293void CBackendDesktop::slotKeyPressEvent(QKeyEvent *event)
294{
295 QKeyEvent* e = new QKeyEvent(event->type(), event->key(),
296 event->modifiers(), event->text());
297 QCoreApplication::postEvent(this, e);
298 WakeUp();
299}
300
301void CBackendDesktop::slotKeyReleaseEvent(QKeyEvent *event)
302{
303 QKeyEvent* e = new QKeyEvent(event->type(), event->key(),
304 event->modifiers(), event->text());
305 QCoreApplication::postEvent(this, e);
306 WakeUp();
307}
308
309void CBackendDesktop::slotInputMethodEvent(QInputMethodEvent *event)
310{
311 if(event->commitString().isEmpty()) return;
312 QInputMethodEvent* e = new QInputMethodEvent(event->preeditString(), event->attributes());
313 e->setCommitString(event->commitString(), event->replacementStart(), event->replacementLength());
314 QCoreApplication::postEvent(this, e);
315 WakeUp();
316}
317
318void CBackendDesktop::mouseMoveEvent(QMouseEvent *event)
319{
320 qDebug(logMouse) << "Need to implement CBackendDesktop::mouseMoveEvent";
321}
322
323void CBackendDesktop::mousePressEvent(QMouseEvent *event)
324{
325 qDebug(logMouse) << "Need to implement CBackendDesktop::mousePressEvent";
326}
327
328void CBackendDesktop::mouseReleaseEvent(QMouseEvent *event)
329{
330 qDebug(logMouse) << "Need to implement CBackendDesktop::mouseReleaseEvent";
331}
332
333void CBackendDesktop::wheelEvent(QWheelEvent *event)
334{
335 qDebug(logMouse) << "Need to implement CBackendDesktop::wheelEvent";
336}
337
338void CBackendDesktop::keyPressEvent(QKeyEvent *event)
339{
340 qDebug(logMouse) << "Need to implement CBackendDesktop::keyPressEvent";
341}
342
343void CBackendDesktop::keyReleaseEvent(QKeyEvent *event)
344{
345 qDebug(logMouse) << "Need to implement CBackendDesktop::keyReleaseEvent";
346}
347
348void CBackendDesktop::InputMethodEvent(QInputMethodEvent *event)
349{
350 qDebug(logMouse) << "Need to implement CBackendDesktop::InputMethodEvent";
351}
352
354{
355 return 0;
356}
357
358bool CBackendDesktop::event(QEvent *event)
359{
360 //qDebug(log) << "CBackendDesktop::event" << event;
361 switch (event->type()) {
362 case QEvent::MouseButtonPress:
363 case QEvent::MouseButtonDblClick:
364 mousePressEvent((QMouseEvent*)event);
365 break;
366 case QEvent::MouseButtonRelease:
367 mouseReleaseEvent((QMouseEvent*)event);
368 break;
369 case QEvent::MouseMove:
370 mouseMoveEvent((QMouseEvent*)event);
371 break;
372 case QEvent::Wheel:
373 wheelEvent((QWheelEvent*)event);
374 break;
375 case QEvent::KeyPress:
376 keyPressEvent((QKeyEvent*)event);
377 break;
378 case QEvent::KeyRelease:
379 keyReleaseEvent((QKeyEvent*)event);
380 break;
381 case QEvent::InputMethod:
382 InputMethodEvent((QInputMethodEvent*) event);
383 break;
384#if HAVE_QT6_RECORD
385 case TypeRecordVideo:
386 RecordVideo((QRecordVideoEvent*)event);
387 break;
388#endif
389 default:
390 return QObject::event(event);
391 }
392
393 event->accept();
394 return true;
395}
396
397#if HAVE_QT6_RECORD
398void CBackendDesktop::slotRecord(bool bRecord)
399{
400 qDebug(log) << Q_FUNC_INFO << bRecord;
401 if(bRecord) {
402 if(QMediaRecorder::RecordingState == m_Recorder.recorderState())
403 return;
404 (*m_pParameterRecord) >> m_Recorder;
405 m_CaptureSession.setVideoFrameInput(&m_VideoFrameInput);
406 m_CaptureSession.setRecorder(&m_Recorder);
407 m_Recorder.record();
408 } else {
409 m_Recorder.stop();
410 m_CaptureSession.setVideoFrameInput(nullptr);
411 m_CaptureSession.setAudioBufferInput(nullptr);
412 m_CaptureSession.setRecorder(nullptr);
413 }
414 emit sigRecordVideo(bRecord, m_pParameterRecord->GetVideoFrameRate());
415}
416
417void CBackendDesktop::slotRecordPause(bool bPause)
418{
419 qDebug(log) << Q_FUNC_INFO << bPause;
420 if(bPause) {
421 if(m_Recorder.recorderState() == QMediaRecorder::RecordingState)
422 m_Recorder.pause();
423 } else {
424 if(m_Recorder.recorderState() == QMediaRecorder::PausedState)
425 m_Recorder.record();
426 }
427}
428
429void CBackendDesktop::slotRecordVideo(const QImage &img)
430{
432 if(!e) return;
433 QCoreApplication::postEvent(this, e);
434 WakeUp();
435}
436
437void CBackendDesktop::RecordVideo(QRecordVideoEvent *e)
438{
439 //qDebug(log) << "Update image";
440 if(!e) return;
441 if(QMediaRecorder::RecordingState != m_Recorder.recorderState()) {
442 qCritical(log) << "Recorder is inavailable";
443 return;
444 }
445 QVideoFrame frame(e->GetImage());
446 bool bRet = m_VideoFrameInput.sendVideoFrame(frame);
447 if(!bRet) {
448 //TODO: 放入未成功发送队列,
449 // 当 QVideoFrameInput::readyToSendVideoFrame() 时,再发送
450 qDebug(log) << "m_VideoFrameInput.sendVideoFrame fail";
451 }
452}
453
455{
456 slotRecord(false);
457 return CBackend::Stop();
458}
459#endif
void sigUpdateRect(const QRect &r, const QImage &image)
通知视图,图像更新
int SetViewer(CFrmViewer *pView)
virtual void slotClipBoardChanged()=0
当剪切板发生改变时调用
virtual int WakeUp() override
唤醒后台线程
后端接口。它由协议插件实现。 它默认启动一个定时器来开启一个非 Qt 事件循环(就是普通的循环处理)。 详见: Start()、 slotTimeOut()、 OnProcess() 。 当然,它仍然支...
Definition Backend.h:42
virtual int Stop()
停止
Definition Backend.cpp:92
void sigRunning()
当插件开始成功后触发。仅由插件触发
The scroll form class
Definition FrmScroll.h:17
用于显示从 CConnectDesktop 输出的图像,和向 CConnectDesktop 发送键盘、鼠标事件。
Definition FrmViewer.h:48
远程桌面操作接口
virtual QWidget * GetViewer() override
得到显示视图
virtual CParameterBase * GetParameter()
Get parameter