PonyPlayer
hurricane.hpp
浏览该文件的文档.
1//
2// Created by ColorsWind on 2022/5/6.
3//
4
5#pragma once
6#ifndef PONYPLAYER_HURRICANE_HPP
7#define PONYPLAYER_HURRICANE_HPP
8
9#include <QObject>
10#include <utility>
11#include "framecontroller.hpp"
12#include "fireworks.hpp"
13
28class Hurricane : public Fireworks {
29Q_OBJECT
30 QML_ADDED_IN_VERSION(1, 0)
31 QML_ELEMENT
32public:
44 PAUSED
45 };
46
47 Q_ENUM(HurricaneState)
48
49 QML_ELEMENT
50 Q_PROPERTY(qreal pitch READ getPitch WRITE setPitch NOTIFY pitchChanged)
51 Q_PROPERTY(HurricaneState state READ getState NOTIFY stateChanged FINAL)
52 Q_PROPERTY(QStringList audioDeviceList READ getAudioDeviceList NOTIFY audioOutputDeviceChanged)
53 Q_PROPERTY(QStringList tracks READ getTracks NOTIFY openFileResult)
54 Q_PROPERTY(bool backwardStatus READ isBackward NOTIFY backwardStatusChanged)
55 Q_PROPERTY(int track READ getTrack WRITE setTrack NOTIFY trackChanged)
56 Q_PROPERTY(
58 Q_PROPERTY(double speed READ getSpeed WRITE setSpeed NOTIFY speedChanged)
59
60
61private:
62 bool backwardStatus = false;
63private:
65private:
66 FrameController *frameController;
67 int track = -1;
68 double speed = 1.0;
69public:
70 explicit Hurricane(QQuickItem *parent = nullptr) : Fireworks(parent) {
71 frameController = new FrameController(this);
72
73 connect(this, &Hurricane::signalStart, frameController, &FrameController::start);
74 connect(this, &Hurricane::signalPause, frameController, &FrameController::pause);
75
76 connect(this, &Hurricane::signalOpenFile, frameController, &FrameController::openFile);
77
78 connect(frameController, &FrameController::openFileResult, this, &Hurricane::slotOpenFileResult);
79 connect(this, &Hurricane::signalClose, frameController, &FrameController::close);
80 connect(frameController, &FrameController::setPicture, this, &Hurricane::setVideoFrame);
81
82 connect(this, &Hurricane::signalSeek, frameController, &FrameController::seek);
83 connect(frameController, &FrameController::signalPositionChangedBySeek, this,
84 &Hurricane::slotPositionChangedBySeek);
85
86 connect(frameController, &FrameController::playbackStateChanged, this, &Hurricane::slotPlaybackStateChanged);
87
88 connect(this, &Hurricane::stateChanged, [this] {
89 qDebug() << "State Changed to" << QVariant::fromValue(state).toString();
90 });
91
92 connect(frameController, &FrameController::signalAudioOutputDevicesChanged, this,
95 connect(frameController, &FrameController::resourcesEnd, this, &Hurricane::resourcesEnd);
96 emit signalPlayerInitializing(QPrivateSignal());
97#ifdef DEBUG_FLAG_AUTO_OPEN
98 openFile(QUrl::fromLocalFile(QDir::homePath().append(u"/581518754-1-208.mp4"_qs)).url());
99#endif
100 }
101
102 virtual ~Hurricane() override {
103 frameController->pause();
104 frameController->deleteLater();
105 qWarning() << "Destroy HurricanePlayer.";
106 }
107
109
110 int getTrack() {
111 return track;
112 }
113
114 double getSpeed() {
115 return speed;
116 }
117
118 bool isBackward() { return backwardStatus; }
119
120 QStringList getAudioDeviceList() { return frameController->getAudioDeviceList(); }
121
122
123signals:
124
131
136 void openFileResult(PonyPlayer::OpenFileResultType result, QPrivateSignal);
137
142
144
146
148
150
152
154
156
157Q_SIGNALS:
158
159 // 下面这些方法用于与 VideoPlayWorker 通信
160 // 约定两者通信的方法信号以 signal 开头, 槽函数以 slot 开头
161 // 约定信号只能由所属的类的实例 emit
162 void signalPlayerInitializing(QPrivateSignal);
163
164 void signalStart(QPrivateSignal);
165
166 void signalPause(QPrivateSignal);
167
168 void signalClose(QPrivateSignal);
169
170 void signalOpenFile(const QString &path, QPrivateSignal);
171
172 void signalSeek(qreal pos, QPrivateSignal);
173
174
175public slots:
176
185 Q_INVOKABLE void openFile(const QString &url, bool autoClose = true) {
186 if (autoClose && (state == HurricaneState::PLAYING || state == PRE_PLAY)) {
187 emit pause();
188 }
189 if (autoClose && (state == HurricaneState::PAUSED || state == PRE_PAUSE)) {
190 emit close();
191 }
192 if (state == HurricaneState::CLOSING || state == HurricaneState::INVALID) {
193 if (state == HurricaneState::CLOSING) {
194 // wait for the operation to complete
195 QCoreApplication::processEvents();
196 }
197 state = HurricaneState::LOADING;
198 emit stateChanged();
199 backwardStatus = false;
201 emit signalOpenFile(QUrl(url).toLocalFile(), QPrivateSignal());
202 qDebug() << "Open file:" << url;
203 }
204 };
205
206
212 Q_INVOKABLE void start() {
213 if (state == HurricaneState::PAUSED || state == HurricaneState::PRE_PAUSE) {
214 state = HurricaneState::PRE_PLAY;
215 emit stateChanged();
216 emit signalStart(QPrivateSignal());
217 qDebug() << "Start play video.";
218 }
219 }
220
226 Q_INVOKABLE void pause() {
227 if (state == HurricaneState::PLAYING || state == HurricaneState::PRE_PLAY) {
228 state = HurricaneState::PRE_PAUSE;
229 emit stateChanged();
230 emit signalPause(QPrivateSignal());
231 qDebug() << "Pause.";
232 }
233 }
234
240 Q_INVOKABLE void close() {
241 if (state == HurricaneState::PRE_PAUSE || state == HurricaneState::PAUSED) {
242 state = HurricaneState::CLOSING;
243 emit stateChanged();
245 emit signalClose(QPrivateSignal());
246 }
247 }
248
253 Q_INVOKABLE void setVolume(qreal volume) {
254 frameController->setVolume(volume);
255 }
256
261 Q_INVOKABLE void setPitch(qreal pitch) {
262 frameController->setPitch(pitch);
263 }
264
269 Q_INVOKABLE void setSpeed(qreal speed) {
270 frameController->setSpeed(speed);
271 this->speed = speed;
272 emit speedChanged();
273 }
274
279 Q_INVOKABLE void setCurrentOutputDevice(QString deviceName) {
280 frameController->setSelectedAudioOutputDevice(std::move(deviceName));
281 }
282
286 Q_INVOKABLE QString getCurrentOutputDevice() {
287 return frameController->getSelectedAudioOutputDevice();
288 }
289
294 Q_INVOKABLE qreal getAudioDuration() { return frameController->getAudioDuration(); }
295
300 Q_INVOKABLE qreal getVideoDuration() { return frameController->getVideoDuration(); }
301
306 Q_INVOKABLE qreal getPTS() {
307 qreal pts = frameController->getPreferablePos();
308 if (std::isnan(pts)) {
309 qWarning() << "getPTS return NaN";
310 }
311 return pts;
312 }
313
320 Q_INVOKABLE void seek(qreal pos) {
321 // only available on PLAY/PAUSE
322 bool playing = false;
323 switch (state) {
324 case HurricaneState::PLAYING:
325 case HurricaneState::PRE_PLAY:
326 playing = true;
327 /* fall through */
328 case HurricaneState::PAUSED:
329 case HurricaneState::PRE_PAUSE:
330 break;
331 default:
332 return;
333 }
334 if (pos < 0 || pos > getVideoDuration())
335 return;
337 emit stateChanged();
338// emit signalPause(QPrivateSignal());
339 emit signalSeek(pos, QPrivateSignal());
340 if (playing) {
341 emit signalStart(QPrivateSignal());
342 }
343 qDebug() << "HurricanePlayer: Seek" << pos;
344 }
345
346 Q_INVOKABLE QStringList getTracks() {
347 if (state == LOADING || state == INVALID) {
348 qWarning() << "Get tracks when" << state;
349 }
350 return frameController->getTracks();
351 }
352
353 Q_INVOKABLE void setTrack(int i) {
354 bool playing = false;
355 switch (state) {
356 case HurricaneState::PLAYING:
357 case HurricaneState::PRE_PLAY:
358 playing = true;
359 /* fall through */
360 case HurricaneState::PAUSED:
361 case HurricaneState::PRE_PAUSE:
362 break;
363 default:
364 return;
365 }
367 emit stateChanged();
368 frameController->setTrack(i);
369 track = i;
370 emit trackChanged();
371 if (playing) {
372 emit signalStart(QPrivateSignal());
373 }
374
375 qDebug() << "Set Music Track" << i;
376 }
377
378
379 Q_INVOKABLE void forward() {
380 bool playing = false;
381 switch (state) {
382 case HurricaneState::PLAYING:
383 case HurricaneState::PRE_PLAY:
384 playing = true;
385 /* fall through */
386 case HurricaneState::PAUSED:
387 case HurricaneState::PRE_PAUSE:
388 break;
389 default:
390 return;
391 }
393 emit stateChanged();
394 backwardStatus = false;
396 frameController->forward();
397 if (playing) {
398 emit signalStart(QPrivateSignal());
399 }
400 qDebug() << "forward";
401 }
402
403 Q_INVOKABLE void backward() {
404 bool playing = false;
405 switch (state) {
406 case HurricaneState::PLAYING:
407 case HurricaneState::PRE_PLAY:
408 playing = true;
409 /* fall through */
410 case HurricaneState::PAUSED:
411 case HurricaneState::PRE_PAUSE:
412 break;
413 default:
414 return;
415 }
417 emit stateChanged();
418 backwardStatus = true;
420 frameController->backward();
421 if (playing) {
422 emit signalStart(QPrivateSignal());
423 }
424 qDebug() << "backward";
425 }
426
427 Q_INVOKABLE void toggleBackward() {
428 if (isBackward()) {
429 forward();
430 } else {
431 backward();
432 }
433 }
434
435 Q_INVOKABLE bool hasVideo() {
436 return frameController != nullptr && frameController->hasVideo();
437 }
438
439 Q_INVOKABLE qreal getPitch() {
440 return frameController ? frameController->getPitch() : 1.0;
441 }
442
443
444private slots:
445
446 void slotPositionChangedBySeek() { emit positionChangedBySeek(); }
447
448 void slotPlaybackStateChanged(bool isPlaying) {
449 if (isPlaying) {
450 state = PLAYING;
451 } else {
452 state = PAUSED;
453 }
454 emit stateChanged();
455 };
456
457 void slotOpenFileResult(PonyPlayer::OpenFileResultType result) {
459 state = PAUSED;
460 track = 0;
461 } else {
462 state = INVALID;
463 track = -1;
464 }
465 emit openFileResult(result, QPrivateSignal());
466 emit trackChanged();
467 emit stateChanged();
468 }
469
470
471};
472
473
474#endif //PONYPLAYER_HURRICANE_HPP
Definition: fireworks.hpp:10
void setVideoFrame(const VideoFrameRef &pic)
Definition: fireworks.hpp:112
将解码拿到的帧传递给输出.
Definition: framecontroller.hpp:16
void setVolume(qreal volume)
Definition: framecontroller.hpp:151
void pause()
Definition: framecontroller.hpp:167
void setPitch(qreal pitch)
Definition: framecontroller.hpp:153
void playbackStateChanged(bool isPlaying)
QStringList getTracks()
Definition: framecontroller.hpp:145
bool hasVideo()
Definition: framecontroller.hpp:149
qreal getPitch()
Definition: framecontroller.hpp:147
qreal getVideoDuration()
Definition: framecontroller.hpp:139
PONY_THREAD_SAFE void backward()
Definition: framecontroller.hpp:117
void openFile(const QString &path)
Definition: framecontroller.hpp:161
void openFileResult(PonyPlayer::OpenFileResultType result)
void setSpeed(qreal speed)
Definition: framecontroller.hpp:155
void setSelectedAudioOutputDevice(QString deviceName)
Definition: framecontroller.hpp:111
void close()
Definition: framecontroller.hpp:179
void signalPositionChangedBySeek()
void signalAudioOutputDevicesChanged()
qreal getAudioDuration()
Definition: framecontroller.hpp:133
void setPicture(VideoFrameRef pic)
void setTrack(int i)
Definition: framecontroller.hpp:107
void seek(qreal seekPos)
Definition: framecontroller.hpp:191
void signalDeviceSwitched()
void start()
Definition: framecontroller.hpp:185
QStringList getAudioDeviceList()
Definition: framecontroller.hpp:157
QString getSelectedAudioOutputDevice()
Definition: framecontroller.hpp:115
PONY_THREAD_SAFE qreal getPreferablePos()
Definition: framecontroller.hpp:125
PONY_THREAD_SAFE void forward()
Definition: framecontroller.hpp:121
播放器 QuickItem 组件,提供暴露给 QML 的接口。
Definition: hurricane.hpp:28
HurricaneState
Definition: hurricane.hpp:37
@ PAUSED
已暂停
Definition: hurricane.hpp:44
@ PRE_PLAY
准备播放, 这是一个瞬时状态, 将会很快转为
Definition: hurricane.hpp:41
@ LOADING
正在加载, 这是一个瞬时状态
Definition: hurricane.hpp:39
@ PLAYING
正在播放
Definition: hurricane.hpp:42
@ INVALID
文件无效
Definition: hurricane.hpp:40
@ PRE_PAUSE
请求暂停, 这是一个瞬时状态
Definition: hurricane.hpp:43
@ CLOSING
正在关闭当前文件, 这是一个瞬时状态
Definition: hurricane.hpp:38
Q_INVOKABLE QString getCurrentOutputDevice()
Definition: hurricane.hpp:286
QStringList getAudioDeviceList()
Definition: hurricane.hpp:120
Q_INVOKABLE qreal getPitch()
Definition: hurricane.hpp:439
Q_INVOKABLE qreal getPTS()
Definition: hurricane.hpp:306
void positionChangedBySeek()
void signalPause(QPrivateSignal)
bool backwardStatus
Definition: hurricane.hpp:54
virtual ~Hurricane() override
Definition: hurricane.hpp:102
void backwardStatusChanged()
HurricaneState state
Definition: hurricane.hpp:51
Q_INVOKABLE void setPitch(qreal pitch)
Definition: hurricane.hpp:261
void openFileResult(PonyPlayer::OpenFileResultType result, QPrivateSignal)
Q_INVOKABLE void openFile(const QString &url, bool autoClose=true)
Definition: hurricane.hpp:185
Q_INVOKABLE void pause()
Definition: hurricane.hpp:226
void trackChanged()
HurricaneState getState()
Definition: hurricane.hpp:108
Q_INVOKABLE void setVolume(qreal volume)
Definition: hurricane.hpp:253
Q_INVOKABLE void forward()
Definition: hurricane.hpp:379
double speed
Definition: hurricane.hpp:58
void signalSeek(qreal pos, QPrivateSignal)
void audioOutputDeviceChanged()
void currentOutputDeviceChanged()
Q_INVOKABLE void backward()
Definition: hurricane.hpp:403
void signalPlayerInitializing(QPrivateSignal)
bool isBackward()
Definition: hurricane.hpp:118
double getSpeed()
Definition: hurricane.hpp:114
Q_INVOKABLE void setTrack(int i)
Definition: hurricane.hpp:353
int getTrack()
Definition: hurricane.hpp:110
QStringList audioDeviceList
Definition: hurricane.hpp:52
void speedChanged()
void stateChanged()
int track
Definition: hurricane.hpp:55
Q_INVOKABLE void setCurrentOutputDevice(QString deviceName)
Definition: hurricane.hpp:279
void pitchChanged()
Q_INVOKABLE void toggleBackward()
Definition: hurricane.hpp:427
Q_INVOKABLE void seek(qreal pos)
Definition: hurricane.hpp:320
Q_INVOKABLE qreal getAudioDuration()
Definition: hurricane.hpp:294
QString currentOutputDevice
Definition: hurricane.hpp:57
Q_INVOKABLE void start()
Definition: hurricane.hpp:212
Q_INVOKABLE void close()
Definition: hurricane.hpp:240
Q_INVOKABLE bool hasVideo()
Definition: hurricane.hpp:435
Q_INVOKABLE qreal getVideoDuration()
Definition: hurricane.hpp:300
QStringList tracks
Definition: hurricane.hpp:53
Q_INVOKABLE void setSpeed(qreal speed)
Definition: hurricane.hpp:269
QML_ELEMENTqreal pitch
Definition: hurricane.hpp:50
void signalOpenFile(const QString &path, QPrivateSignal)
void resourcesEnd()
Q_INVOKABLE QStringList getTracks()
Definition: hurricane.hpp:346
void signalClose(QPrivateSignal)
void signalStart(QPrivateSignal)
Definition: frame.hpp:47
OpenFileResultType
Definition: dispatcher.hpp:32
@ FAILED
打开文件失败
Definition: dispatcher.hpp:33