forked from mpc-qt/mpc-qt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmpvwidget.h
393 lines (325 loc) · 11.7 KB
/
mpvwidget.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
#ifndef MPVWIDGET_H
#define MPVWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLTexture>
#include <QTimer>
#include <QVariant>
#include <QSet>
#include <QMap>
#include <functional>
#include <mpv/client.h>
#include <mpv/render.h>
#include <mpv/render_gl.h>
#include "qthelper.hpp"
#include "helpers.h"
class QLayout;
class QMainWindow;
class QThread;
class QTimer;
class MpvWidgetInterface;
class MpvController;
class LogoDrawer;
class MpvObject : public QObject
{
Q_OBJECT
typedef std::function<void(MpvObject*,bool,const QVariant&)> PropertyDispatchFunction;
typedef QMap<QString, PropertyDispatchFunction> PropertyDispatchMap;
public:
explicit MpvObject(QObject *owner, const QString &clientName = "mpv");
~MpvObject();
void setHostLayout(QLayout *hostLayout);
void setHostWindow(QMainWindow *hostWindow);
void setWidgetType(Helpers::MpvWidgetType widgetType, MpvWidgetInterface *customWidget = nullptr);
QString mpvVersion();
MpvController *controller();
QWidget *mpvWidget();
QList<AudioDevice> audioDevices();
QStringList supportedProtocols();
void showMessage(QString message);
void showStatsPage(int page);
int cycleStatsPage();
int selectedStatsPage();
void urlOpen(QUrl url);
void fileOpen(QString filename);
void discFilesOpen(QString path);
void stopPlayback();
void stepBackward();
void stepForward();
void seek(double amount, bool exact);
void screenshot(const QString &fileName, Helpers::ScreenshotRender render);
void setMouseHideTime(int msec);
void setLogoUrl(const QString &filename);
void setLogoBackground(const QColor &color);
void setSubFile(QString filename);
void addSubFile(QString filename);
void setSubtitlesDelay(int subDelayStep);
int64_t chapter();
bool setChapter(int64_t chapter);
QString mediaTitle();
void setMute(bool yes);
void setPaused(bool yes);
void setSpeed(double speed);
void setTime(double position);
void setTimeSync(double position);
void setLoopPoints(double first, double end);
void setAudioTrack(int64_t id);
void setSubtitleTrack(int64_t id);
void setVideoTrack(int64_t id);
void setDrawLogo(bool yes);
void setVolume(int64_t volume);
void setClientDebuggingMessages(bool yes);
void setMpvLogLevel(QString logLevel);
void setSendKeyEvents(bool enabled);
void setSendMouseEvents(bool enabled);
bool eofReached();
double playLength();
double playTime();
QSize videoSize();
bool clientDebuggingMessages();
void setCachedMpvOption(const QString &option, const QVariant &value);
QVariant blockingMpvCommand(QVariant params);
QVariant blockingSetMpvPropertyVariant(QString name, QVariant value);
QVariant blockingSetMpvOptionVariant(QString name, QVariant value);
QVariant getMpvPropertyVariant(QString name);
signals:
void ctrlContinueHook(uint64_t mpvId);
void ctrlCommand(QVariant params);
void ctrlSetOptionVariant(QString name, QVariant value);
void ctrlSetPropertyVariant(QString name, QVariant value);
void ctrlSetLogLevel(QString level);
void ctrlShowStats(int page);
void audioDeviceList(const QList<AudioDevice> audioDevices);
void playTimeChanged(double time);
void playLengthChanged(double length);
void seekableChanged(bool yes);
void playbackLoading();
void playbackStarted();
void pausedChanged(bool yes);
void eofReachedChanged(bool eof);
void playbackFinished();
void playbackIdling();
void mediaTitleChanged(QString title);
void metaDataChanged(QVariantMap metadata);
void chapterDataChanged(QVariantMap metadata);
void chaptersChanged(QVariantList chapters);
void tracksChanged(QVariantList tracks);
void videoSizeChanged(QSize size);
void fpsChanged(double fps);
void avsyncChanged(double sync);
void displayFramedropsChanged(int64_t count);
void decoderFramedropsChanged(int64_t cout);
void audioBitrateChanged(double bitrate);
void videoBitrateChanged(double bitrate);
void fileNameChanged(QString filename);
void fileFormatChanged(QString format);
void fileSizeChanged(int64_t size);
void fileCreationTimeChanged(int64_t secsSinceEpoch);
void filePathChanged(QString path);
void subTextChanged(QString subText);
void playlistChanged(QVariantList playlist);
void audioTrackSet(int64_t id);
void subtitleTrackSet(int64_t id);
void videoTrackSet(int64_t id);
void logoSizeChanged(QSize size);
void mouseMoved(int x, int y);
void mousePress(int x, int y, int btn);
void keyPress(int key);
void keyRelease(int key);
private:
void setMpvPropertyVariant(QString name, QVariant value);
void setMpvOptionVariant(QString name, QVariant value);
void showCursor();
void hideCursor();
private slots:
void ctrl_mpvPropertyChanged(QString name, QVariant v);
void ctrl_hookEvent(QString name, uint64_t selfId, uint64_t mpvId);
void ctrl_unhandledMpvEvent(int eventLevel);
void ctrl_videoSizeChanged(QSize size);
void self_playTimeChanged(double playTime);
void self_playLengthChanged(double playLength);
void self_metadata(QVariantMap metadata);
void self_audioDeviceList(const QVariantList &list);
void hideTimer_timeout();
void self_mouseMoved(int x, int y);
void self_mousePress(int x, int y, int btn);
void self_keyPress(int key);
void self_keyRelease(int key);
private:
static PropertyDispatchMap propertyDispatch;
Helpers::MpvWidgetType widgetType = Helpers::NullWidget;
QLayout *hostLayout = nullptr;
QMainWindow *hostWindow = nullptr;
MpvController *ctrl = nullptr;
MpvWidgetInterface *widget = nullptr;
QThread *worker = nullptr;
QTimer *hideTimer = nullptr;
QVariantMap cachedState;
QSize videoSize_;
double playTime_ = 0.0;
double playLength_ = 0.0;
int shownStatsPage = 0;
bool loopImages = true;
bool debugMessages = false;
bool sendMouseEvents = false;
bool sendKeyEvents = false;
};
class MpvWidgetInterface
{
public:
explicit MpvWidgetInterface(MpvObject *object);
virtual ~MpvWidgetInterface();
void setController(MpvController *controller);
virtual QWidget *self() = 0;
virtual void initMpv() = 0;
virtual void setLogoUrl(const QString &filename);
virtual void setLogoBackground(const QColor &color);
virtual void setDrawLogo(bool yes);
protected:
MpvObject *mpvObject = nullptr;
MpvController *ctrl = nullptr;
};
Q_DECLARE_INTERFACE(MpvWidgetInterface, "cmdrkotori.mpc-qt.MpvWidgetInterface/1.0");
class MpvGlWidget : public QOpenGLWidget, public MpvWidgetInterface
{
Q_OBJECT
Q_INTERFACES(MpvWidgetInterface)
public:
explicit MpvGlWidget(MpvObject *object, QWidget *parent = nullptr);
~MpvGlWidget();
QWidget *self();
void initMpv();
void setLogoUrl(const QString &filename);
void setLogoBackground(const QColor &color);
void setDrawLogo(bool yes);
static void *get_proc_address(void *ctx, const char *name);
signals:
void mouseMoved(int x, int y);
void mousePress(int x, int y);
protected:
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
private:
static void render_update(void *ctx);
private slots:
void maybeUpdate();
void self_frameSwapped();
void self_playbackStarted();
void self_playbackFinished();
private:
mpv_render_context *render = nullptr;
LogoDrawer *logo = nullptr;
bool drawLogo = true;
int glWidth = 0, glHeight = 0;
bool windowDragging = false;
QPointF mousePressPosition;
};
// FIXME: implement MpvVulkanCbWidget
typedef MpvGlWidget MpvVulkanCbWidget;
// FIXME: implement MpvEmbedWidget
typedef MpvGlWidget MpvEmbedWidget;
class MpvErrorCode {
public:
MpvErrorCode() {}
MpvErrorCode(int value) : value(value) {}
MpvErrorCode(const MpvErrorCode &mec) : value(mec.value) {}
~MpvErrorCode() {}
int errorcode() { return value; }
private:
int value = 0;
};
Q_DECLARE_METATYPE(MpvErrorCode)
// This wraps a lambda so that it is invoked in the calling thread. i.e. use
// QMetaObject::invokeMethod on the controller's async functions to pass
// through this object, like this:
// getPropertyVariantAsync("xyz", new MpvCallback([](const QVariant &v) {
// ...
// }));
class MpvCallback : public QObject {
Q_OBJECT
public:
typedef std::function<void(QVariant)> Callback;
explicit MpvCallback(const Callback &callback, QObject *owner = nullptr);
public slots:
void reply(QVariant value);
private:
Callback callback;
};
// This controller attempts to shove as much libmpv related business off of
// the main thread.
class MpvController : public QObject
{
Q_OBJECT
public:
struct MpvProperty {
QString name;
uint64_t userData;
mpv_format format;
MpvProperty(const QString &name, uint64_t userData, mpv_format format)
: name(name), userData(userData), format(format) {}
};
typedef QVector<MpvProperty> PropertyList;
struct MpvOption {
QString name;
QVariant value;
};
typedef QVector<MpvOption> OptionList;
MpvController(QObject *parent = nullptr);
~MpvController();
signals:
void durationChanged(int value);
void positionChanged(int value);
void mpvPropertyChanged(QString name, QVariant v, uint64_t userData);
void logMessageByParts(QString prefix, QString level, QString msg);
//void logMessage(QString message);
void clientMessage(uint64_t id, QStringList args);
void videoSizeChanged(QSize size);
void hookEvent(QString hookName, uint64_t selfId, uint64_t mpvId);
void unhandledMpvEvent(int eventNumber);
public slots:
void create(const MpvController::OptionList &earlyOptions);
void stop();
mpv_render_context *createRenderContext(mpv_render_param *params);
void destroyRenderContext(mpv_render_context *render);
void addHook(const QString &name, uint64_t selfId);
void continueHook(uint64_t mpvId);
int observeProperties(const MpvController::PropertyList &properties,
const QSet<QString> &throttled = QSet<QString>());
int unobservePropertiesById(const QSet<uint64_t> &ids);
void setThrottleTime(int msec);
QString clientName();
QStringList protocolList();
int64_t timeMicroseconds();
unsigned long apiVersion();
void setLogLevel(QString logLevel);
void showStatsPage(int page);
int setOptionVariant(QString name, const QVariant &value);
QVariant command(const QVariant ¶ms);
int setPropertyVariant(const QString &name, const QVariant &value);
QVariant getPropertyVariant(const QString &name);
int setPropertyString(const QString &name, const QString &value);
QString getPropertyString(const QString &name);
void commandAsync(const QVariant ¶ms, MpvCallback *callback);
void setPropertyVariantAsync(const QString &name, const QVariant &value, MpvCallback *callback);
void getPropertyVariantAsync(const QString &name, MpvCallback *callback);
void parseMpvEvents();
private:
void setThrottledProperty(const QString &name, const QVariant &v, uint64_t userData);
void flushProperties();
void handleMpvEvent(mpv_event *event);
static void mpvWakeup(void *ctx);
mpv::qt::Handle mpv;
QStringList protocolList_;
QSize lastVideoSize = QSize(0,0);
QTimer *throttler = nullptr;
QSet<QString> throttledProperties;
typedef QMap<QString,QPair<QVariant,uint64_t>> ThrottledValueMap;
ThrottledValueMap throttledValues;
int shownStatsPage = 0;
};
#endif // MPVWIDGET_H