1 #include "waveform/waveformwidgetfactory.h"
2
3 #include <QGLFormat>
4 #include <QGLShaderProgram>
5 #include <QGuiApplication>
6 #include <QOpenGLFunctions>
7 #include <QStringList>
8 #include <QTime>
9 #include <QWidget>
10 #include <QWindow>
11 #include <QtDebug>
12
13 #include "control/controlpotmeter.h"
14 #include "moc_waveformwidgetfactory.cpp"
15 #include "util/cmdlineargs.h"
16 #include "util/math.h"
17 #include "util/performancetimer.h"
18 #include "util/timer.h"
19 #include "waveform/guitick.h"
20 #include "waveform/sharedglcontext.h"
21 #include "waveform/visualsmanager.h"
22 #include "waveform/vsyncthread.h"
23 #include "waveform/widgets/emptywaveformwidget.h"
24 #include "waveform/widgets/glrgbwaveformwidget.h"
25 #include "waveform/widgets/glsimplewaveformwidget.h"
26 #include "waveform/widgets/glslwaveformwidget.h"
27 #include "waveform/widgets/glvsynctestwidget.h"
28 #include "waveform/widgets/glwaveformwidget.h"
29 #include "waveform/widgets/hsvwaveformwidget.h"
30 #include "waveform/widgets/qthsvwaveformwidget.h"
31 #include "waveform/widgets/qtrgbwaveformwidget.h"
32 #include "waveform/widgets/qtsimplewaveformwidget.h"
33 #include "waveform/widgets/qtvsynctestwidget.h"
34 #include "waveform/widgets/qtwaveformwidget.h"
35 #include "waveform/widgets/rgbwaveformwidget.h"
36 #include "waveform/widgets/softwarewaveformwidget.h"
37 #include "waveform/widgets/waveformwidgetabstract.h"
38 #include "widget/wvumeter.h"
39 #include "widget/wwaveformviewer.h"
40
41 namespace {
42 // Returns true if the given waveform should be rendered.
shouldRenderWaveform(WaveformWidgetAbstract * pWaveformWidget)43 bool shouldRenderWaveform(WaveformWidgetAbstract* pWaveformWidget) {
44 if (pWaveformWidget == nullptr ||
45 pWaveformWidget->getWidth() == 0 ||
46 pWaveformWidget->getHeight() == 0) {
47 return false;
48 }
49
50 auto* glw = qobject_cast<QGLWidget*>(pWaveformWidget->getWidget());
51 if (glw == nullptr) {
52 // Not a QGLWidget. We can simply use QWidget::isVisible.
53 auto* qwidget = qobject_cast<QWidget*>(pWaveformWidget->getWidget());
54 return qwidget != nullptr && qwidget->isVisible();
55 }
56
57 if (glw == nullptr || !glw->isValid() || !glw->isVisible()) {
58 return false;
59 }
60
61 // Strangely, a widget can have non-zero width/height, be valid and visible,
62 // yet still not show up on the screen. QWindow::isExposed tells us this.
63 const QWindow* window = glw->windowHandle();
64 if (window == nullptr || !window->isExposed()) {
65 return false;
66 }
67
68 return true;
69 }
70 } // anonymous namespace
71
72 ///////////////////////////////////////////
73
WaveformWidgetAbstractHandle()74 WaveformWidgetAbstractHandle::WaveformWidgetAbstractHandle()
75 : m_type(WaveformWidgetType::Count_WaveformwidgetType) {
76 }
77
78 ///////////////////////////////////////////
79
WaveformWidgetHolder()80 WaveformWidgetHolder::WaveformWidgetHolder()
81 : m_waveformWidget(nullptr),
82 m_waveformViewer(nullptr),
83 m_skinContextCache(UserSettingsPointer(), QString()) {
84 }
85
WaveformWidgetHolder(WaveformWidgetAbstract * waveformWidget,WWaveformViewer * waveformViewer,const QDomNode & node,const SkinContext & parentContext)86 WaveformWidgetHolder::WaveformWidgetHolder(WaveformWidgetAbstract* waveformWidget,
87 WWaveformViewer* waveformViewer,
88 const QDomNode& node,
89 const SkinContext& parentContext)
90 : m_waveformWidget(waveformWidget),
91 m_waveformViewer(waveformViewer),
92 m_skinNodeCache(node.cloneNode()),
93 m_skinContextCache(&parentContext) {
94 }
95
96 ///////////////////////////////////////////
97
WaveformWidgetFactory()98 WaveformWidgetFactory::WaveformWidgetFactory()
99 // Set an empty waveform initially. We will set the correct one when skin load finishes.
100 // Concretely, we want to set a non-GL waveform when loading the skin so that the window
101 // loads correctly.
102 : m_type(WaveformWidgetType::EmptyWaveform),
103 m_configType(WaveformWidgetType::EmptyWaveform),
104 m_config(nullptr),
105 m_skipRender(false),
106 m_frameRate(30),
107 m_endOfTrackWarningTime(30),
108 m_defaultZoom(WaveformWidgetRenderer::s_waveformDefaultZoom),
109 m_zoomSync(true),
110 m_overviewNormalized(false),
111 m_openGlAvailable(false),
112 m_openGlesAvailable(false),
113 m_openGLShaderAvailable(false),
114 m_beatGridAlpha(90),
115 m_vsyncThread(nullptr),
116 m_pGuiTick(nullptr),
117 m_pVisualsManager(nullptr),
118 m_frameCnt(0),
119 m_actualFrameRate(0),
120 m_vSyncType(0),
121 m_playMarkerPosition(WaveformWidgetRenderer::s_defaultPlayMarkerPosition) {
122 m_visualGain[All] = 1.0;
123 m_visualGain[Low] = 1.0;
124 m_visualGain[Mid] = 1.0;
125 m_visualGain[High] = 1.0;
126
127 QGLWidget* pGlWidget = SharedGLContext::getWidget();
128 if (pGlWidget && pGlWidget->isValid()) {
129 // will be false if SafeMode is enabled
130
131 pGlWidget->show();
132 // Without a makeCurrent, hasOpenGLShaderPrograms returns false on Qt 5.
133 // and QGLFormat::openGLVersionFlags() returns the maximum known version
134 pGlWidget->makeCurrent();
135
136 QGLFormat::OpenGLVersionFlags version = QGLFormat::openGLVersionFlags();
137
138 auto rendererString = QString();
139 if (QOpenGLContext::currentContext()) {
140 auto glFunctions = QOpenGLFunctions();
141
142 glFunctions.initializeOpenGLFunctions();
143 QString versionString(QLatin1String(
144 reinterpret_cast<const char*>(glFunctions.glGetString(GL_VERSION))));
145 QString vendorString(QLatin1String(
146 reinterpret_cast<const char*>(glFunctions.glGetString(GL_VENDOR))));
147 rendererString = QString(QLatin1String(
148 reinterpret_cast<const char*>(glFunctions.glGetString(GL_RENDERER))));
149
150 // Either GL or GL ES Version is set, not both.
151 qDebug() << QString("openGLVersionFlags 0x%1").arg(version, 0, 16) << versionString << vendorString << rendererString;
152 } else {
153 qDebug() << "QOpenGLContext::currentContext() returns nullptr";
154 qDebug() << "pGlWidget->->windowHandle() =" << pGlWidget->windowHandle();
155 }
156
157 int majorGlVersion = 0;
158 int minorGlVersion = 0;
159 int majorGlesVersion = 0;
160 int minorGlesVersion = 0;
161 if (version == QGLFormat::OpenGL_Version_None) {
162 m_openGLVersion = "None";
163 } else if (version & QGLFormat::OpenGL_Version_4_3) {
164 majorGlVersion = 4;
165 minorGlVersion = 3;
166 } else if (version & QGLFormat::OpenGL_Version_4_2) {
167 majorGlVersion = 4;
168 minorGlVersion = 2;
169 } else if (version & QGLFormat::OpenGL_Version_4_1) {
170 majorGlVersion = 4;
171 minorGlVersion = 1;
172 } else if (version & QGLFormat::OpenGL_Version_4_0) {
173 majorGlVersion = 4;
174 minorGlVersion = 0;
175 } else if (version & QGLFormat::OpenGL_Version_3_3) {
176 majorGlVersion = 3;
177 minorGlVersion = 3;
178 } else if (version & QGLFormat::OpenGL_Version_3_2) {
179 majorGlVersion = 3;
180 minorGlVersion = 2;
181 } else if (version & QGLFormat::OpenGL_Version_3_1) {
182 majorGlVersion = 3;
183 minorGlVersion = 1;
184 } else if (version & QGLFormat::OpenGL_Version_3_0) {
185 majorGlVersion = 3;
186 } else if (version & QGLFormat::OpenGL_Version_2_1) {
187 majorGlVersion = 2;
188 minorGlVersion = 1;
189 } else if (version & QGLFormat::OpenGL_Version_2_0) {
190 majorGlVersion = 2;
191 minorGlVersion = 0;
192 } else if (version & QGLFormat::OpenGL_Version_1_5) {
193 majorGlVersion = 1;
194 minorGlVersion = 5;
195 } else if (version & QGLFormat::OpenGL_Version_1_4) {
196 majorGlVersion = 1;
197 minorGlVersion = 4;
198 } else if (version & QGLFormat::OpenGL_Version_1_3) {
199 majorGlVersion = 1;
200 minorGlVersion = 3;
201 } else if (version & QGLFormat::OpenGL_Version_1_2) {
202 majorGlVersion = 1;
203 minorGlVersion = 2;
204 } else if (version & QGLFormat::OpenGL_Version_1_1) {
205 majorGlVersion = 1;
206 minorGlVersion = 1;
207 } else if (version & QGLFormat::OpenGL_ES_Version_2_0) {
208 m_openGLVersion = "ES 2.0";
209 majorGlesVersion = 2;
210 minorGlesVersion = 0;
211 } else if (version & QGLFormat::OpenGL_ES_CommonLite_Version_1_1) {
212 if (version & QGLFormat::OpenGL_ES_Common_Version_1_1) {
213 m_openGLVersion = "ES 1.1";
214 } else {
215 m_openGLVersion = "ES Common Lite 1.1";
216 }
217 majorGlesVersion = 1;
218 minorGlesVersion = 1;
219 } else if (version & QGLFormat::OpenGL_ES_Common_Version_1_1) {
220 m_openGLVersion = "ES Common Lite 1.1";
221 majorGlesVersion = 1;
222 minorGlesVersion = 1;
223 } else if (version & QGLFormat::OpenGL_ES_CommonLite_Version_1_0) {
224 if (version & QGLFormat::OpenGL_ES_Common_Version_1_0) {
225 m_openGLVersion = "ES 1.0";
226 } else {
227 m_openGLVersion = "ES Common Lite 1.0";
228 }
229 majorGlesVersion = 1;
230 minorGlesVersion = 0;
231 } else if (version & QGLFormat::OpenGL_ES_Common_Version_1_0) {
232 m_openGLVersion = "ES Common Lite 1.0";
233 majorGlesVersion = 1;
234 minorGlesVersion = 0;
235 } else {
236 m_openGLVersion = QString("Unknown 0x%1")
237 .arg(version, 0, 16);
238 }
239
240 if (majorGlVersion != 0) {
241 m_openGLVersion = QString::number(majorGlVersion) + "."
242 + QString::number(minorGlVersion);
243
244 #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
245 if (majorGlVersion * 100 + minorGlVersion >= 201) {
246 // Qt5 requires at least OpenGL 2.1 or OpenGL ES 2.0
247 m_openGlAvailable = true;
248 }
249 #endif
250 } else {
251 if (majorGlesVersion * 100 + minorGlesVersion >= 200) {
252 // Qt5 requires at least OpenGL 2.1 or OpenGL ES 2.0
253 m_openGlesAvailable = true;
254 }
255 }
256
257 m_openGLShaderAvailable =
258 QGLShaderProgram::hasOpenGLShaderPrograms(
259 pGlWidget->context());
260
261 if (!rendererString.isEmpty()) {
262 m_openGLVersion += " (" + rendererString + ")";
263 }
264
265 pGlWidget->hide();
266 }
267
268 evaluateWidgets();
269 m_time.start();
270 }
271
~WaveformWidgetFactory()272 WaveformWidgetFactory::~WaveformWidgetFactory() {
273 if (m_vsyncThread) {
274 delete m_vsyncThread;
275 }
276 }
277
setConfig(UserSettingsPointer config)278 bool WaveformWidgetFactory::setConfig(UserSettingsPointer config) {
279 m_config = config;
280 if (!m_config) {
281 return false;
282 }
283
284 bool ok = false;
285
286 int frameRate = m_config->getValue(ConfigKey("[Waveform]","FrameRate"), m_frameRate);
287 m_frameRate = math_clamp(frameRate, 1, 120);
288
289
290 int endTime = m_config->getValueString(ConfigKey("[Waveform]","EndOfTrackWarningTime")).toInt(&ok);
291 if (ok) {
292 setEndOfTrackWarningTime(endTime);
293 } else {
294 m_config->set(ConfigKey("[Waveform]","EndOfTrackWarningTime"),
295 ConfigValue(m_endOfTrackWarningTime));
296 }
297
298 m_vSyncType = m_config->getValue(ConfigKey("[Waveform]","VSync"), 0);
299
300 double defaultZoom = m_config->getValueString(ConfigKey("[Waveform]","DefaultZoom")).toDouble(&ok);
301 if (ok) {
302 setDefaultZoom(defaultZoom);
303 } else{
304 m_config->set(ConfigKey("[Waveform]","DefaultZoom"), ConfigValue(m_defaultZoom));
305 }
306
307 bool zoomSync = m_config->getValue(ConfigKey("[Waveform]", "ZoomSynchronization"), m_zoomSync);
308 setZoomSync(zoomSync);
309
310 int beatGridAlpha = m_config->getValue(ConfigKey("[Waveform]", "beatGridAlpha"), m_beatGridAlpha);
311 setDisplayBeatGridAlpha(beatGridAlpha);
312
313 WaveformWidgetType::Type type = static_cast<WaveformWidgetType::Type>(
314 m_config->getValueString(ConfigKey("[Waveform]","WaveformType")).toInt(&ok));
315 // Store the widget type on m_configType for later initialization.
316 // We will initialize the objects later because of a problem with GL on QT 5.14.2 on Windows
317 if (!ok || !setWidgetType(type, &m_configType)) {
318 setWidgetType(autoChooseWidgetType(), &m_configType);
319 }
320
321 for (int i = 0; i < FilterCount; i++) {
322 double visualGain = m_config->getValueString(
323 ConfigKey("[Waveform]","VisualGain_" + QString::number(i))).toDouble(&ok);
324
325 if (ok) {
326 setVisualGain(FilterIndex(i), visualGain);
327 } else {
328 m_config->set(ConfigKey("[Waveform]","VisualGain_" + QString::number(i)),
329 QString::number(m_visualGain[i]));
330 }
331 }
332
333 int overviewNormalized = m_config->getValueString(ConfigKey("[Waveform]","OverviewNormalized")).toInt(&ok);
334 if (ok) {
335 setOverviewNormalized(static_cast<bool>(overviewNormalized));
336 } else {
337 m_config->set(ConfigKey("[Waveform]","OverviewNormalized"), ConfigValue(m_overviewNormalized));
338 }
339
340 m_playMarkerPosition = m_config->getValue(ConfigKey("[Waveform]","PlayMarkerPosition"),
341 WaveformWidgetRenderer::s_defaultPlayMarkerPosition);
342 setPlayMarkerPosition(m_playMarkerPosition);
343
344 return true;
345 }
346
destroyWidgets()347 void WaveformWidgetFactory::destroyWidgets() {
348 for (auto& holder : m_waveformWidgetHolders) {
349 WaveformWidgetAbstract* pWidget = holder.m_waveformWidget;
350 holder.m_waveformWidget = nullptr;
351 delete pWidget;
352 }
353 m_waveformWidgetHolders.clear();
354 }
355
addTimerListener(WVuMeter * pWidget)356 void WaveformWidgetFactory::addTimerListener(WVuMeter* pWidget) {
357 // Do not hold the pointer to of timer listeners since they may be deleted.
358 // We don't activate update() or repaint() directly so listener widgets
359 // can decide whether to paint or not.
360 connect(this,
361 &WaveformWidgetFactory::waveformUpdateTick,
362 pWidget,
363 &WVuMeter::maybeUpdate,
364 Qt::DirectConnection);
365 }
366
slotSkinLoaded()367 void WaveformWidgetFactory::slotSkinLoaded() {
368 setWidgetTypeFromConfig();
369 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) && defined __WINDOWS__
370 // This regenerates the waveforms twice because of a bug found on Windows
371 // where the first one fails.
372 // The problem is that the window of the widget thinks that it is not exposed.
373 // (https://doc.qt.io/qt-5/qwindow.html#exposeEvent )
374 setWidgetTypeFromConfig();
375 #endif
376 }
377
setWaveformWidget(WWaveformViewer * viewer,const QDomElement & node,const SkinContext & parentContext)378 bool WaveformWidgetFactory::setWaveformWidget(WWaveformViewer* viewer,
379 const QDomElement& node,
380 const SkinContext& parentContext) {
381 int index = findIndexOf(viewer);
382 if (index != -1) {
383 qDebug() << "WaveformWidgetFactory::setWaveformWidget - "\
384 "viewer already have a waveform widget but it's not found by the factory !";
385 delete viewer->getWaveformWidget();
386 }
387
388 // Cast to widget done just after creation because it can't be perform in
389 // constructor (pure virtual)
390 WaveformWidgetAbstract* waveformWidget = createWaveformWidget(m_type, viewer);
391 viewer->setWaveformWidget(waveformWidget);
392 viewer->setup(node, parentContext);
393
394 // create new holder
395 WaveformWidgetHolder holder(waveformWidget, viewer, node, &parentContext);
396 if (index == -1) {
397 // add holder
398 m_waveformWidgetHolders.push_back(std::move(holder));
399 index = static_cast<int>(m_waveformWidgetHolders.size()) - 1;
400 } else {
401 // update holder
402 DEBUG_ASSERT(index >= 0);
403 m_waveformWidgetHolders[index] = std::move(holder);
404 }
405
406 viewer->setZoom(m_defaultZoom);
407 viewer->setDisplayBeatGridAlpha(m_beatGridAlpha);
408 viewer->setPlayMarkerPosition(m_playMarkerPosition);
409 waveformWidget->resize(viewer->width(), viewer->height());
410 waveformWidget->getWidget()->show();
411 viewer->update();
412
413 qDebug() << "WaveformWidgetFactory::setWaveformWidget - waveform widget added in factory, index" << index;
414
415 return true;
416 }
417
setFrameRate(int frameRate)418 void WaveformWidgetFactory::setFrameRate(int frameRate) {
419 m_frameRate = math_clamp(frameRate, 1, 120);
420 if (m_config) {
421 m_config->set(ConfigKey("[Waveform]","FrameRate"), ConfigValue(m_frameRate));
422 }
423 if (m_vsyncThread) {
424 m_vsyncThread->setSyncIntervalTimeMicros(static_cast<int>(1e6 / m_frameRate));
425 }
426 }
427
setEndOfTrackWarningTime(int endTime)428 void WaveformWidgetFactory::setEndOfTrackWarningTime(int endTime) {
429 m_endOfTrackWarningTime = endTime;
430 if (m_config) {
431 m_config->set(ConfigKey("[Waveform]","EndOfTrackWarningTime"), ConfigValue(m_endOfTrackWarningTime));
432 }
433 }
434
setVSyncType(int type)435 void WaveformWidgetFactory::setVSyncType(int type) {
436 if (m_config) {
437 m_config->set(ConfigKey("[Waveform]","VSync"), ConfigValue((int)type));
438 }
439
440 m_vSyncType = type;
441 if (m_vsyncThread) {
442 m_vsyncThread->setVSyncType(type);
443 }
444 }
445
getVSyncType()446 int WaveformWidgetFactory::getVSyncType() {
447 return m_vSyncType;
448 }
449
setWidgetType(WaveformWidgetType::Type type)450 bool WaveformWidgetFactory::setWidgetType(WaveformWidgetType::Type type) {
451 return setWidgetType(type, &m_type);
452 }
453
setWidgetType(WaveformWidgetType::Type type,WaveformWidgetType::Type * pCurrentType)454 bool WaveformWidgetFactory::setWidgetType(
455 WaveformWidgetType::Type type,
456 WaveformWidgetType::Type* pCurrentType) {
457 if (type == *pCurrentType) {
458 return true;
459 }
460
461 // check if type is acceptable
462 int index = findHandleIndexFromType(type);
463 if (index > -1) {
464 // type is acceptable
465 *pCurrentType = type;
466 if (m_config) {
467 m_config->setValue(
468 ConfigKey("[Waveform]", "WaveformType"),
469 static_cast<int>(*pCurrentType));
470 }
471 return true;
472 }
473
474 // fallback
475 *pCurrentType = WaveformWidgetType::EmptyWaveform;
476 if (m_config) {
477 m_config->setValue(
478 ConfigKey("[Waveform]", "WaveformType"),
479 static_cast<int>(*pCurrentType));
480 }
481 return false;
482 }
483
setWidgetTypeFromConfig()484 bool WaveformWidgetFactory::setWidgetTypeFromConfig() {
485 int empty = findHandleIndexFromType(WaveformWidgetType::EmptyWaveform);
486 int desired = findHandleIndexFromType(m_configType);
487 if (desired == -1) {
488 desired = empty;
489 }
490 return setWidgetTypeFromHandle(desired, true);
491 }
492
setWidgetTypeFromHandle(int handleIndex,bool force)493 bool WaveformWidgetFactory::setWidgetTypeFromHandle(int handleIndex, bool force) {
494 if (handleIndex < 0 || handleIndex >= m_waveformWidgetHandles.size()) {
495 qDebug() << "WaveformWidgetFactory::setWidgetType - invalid handle --> use of 'EmptyWaveform'";
496 // fallback empty type
497 setWidgetType(WaveformWidgetType::EmptyWaveform);
498 return false;
499 }
500
501 WaveformWidgetAbstractHandle& handle = m_waveformWidgetHandles[handleIndex];
502 if (handle.m_type == m_type && !force) {
503 qDebug() << "WaveformWidgetFactory::setWidgetType - type already in use";
504 return true;
505 }
506
507 // change the type
508 setWidgetType(handle.m_type);
509
510 m_skipRender = true;
511 //qDebug() << "recreate start";
512
513 //re-create/setup all waveform widgets
514 for (auto& holder : m_waveformWidgetHolders) {
515 WaveformWidgetAbstract* previousWidget = holder.m_waveformWidget;
516 TrackPointer pTrack = previousWidget->getTrackInfo();
517 //previousWidget->hold();
518 double previousZoom = previousWidget->getZoomFactor();
519 double previousPlayMarkerPosition = previousWidget->getPlayMarkerPosition();
520 int previousbeatgridAlpha = previousWidget->getBeatGridAlpha();
521 delete previousWidget;
522 WWaveformViewer* viewer = holder.m_waveformViewer;
523 WaveformWidgetAbstract* widget = createWaveformWidget(m_type, holder.m_waveformViewer);
524 holder.m_waveformWidget = widget;
525 viewer->setWaveformWidget(widget);
526 viewer->setup(holder.m_skinNodeCache, holder.m_skinContextCache);
527 viewer->setZoom(previousZoom);
528 viewer->setPlayMarkerPosition(previousPlayMarkerPosition);
529 viewer->setDisplayBeatGridAlpha(previousbeatgridAlpha);
530 // resize() doesn't seem to get called on the widget. I think Qt skips
531 // it since the size didn't change.
532 //viewer->resize(viewer->size());
533 widget->resize(viewer->width(), viewer->height());
534 widget->setTrack(pTrack);
535 widget->getWidget()->show();
536 viewer->update();
537 }
538
539 m_skipRender = false;
540 //qDebug() << "recreate done";
541 return true;
542 }
543
setDefaultZoom(double zoom)544 void WaveformWidgetFactory::setDefaultZoom(double zoom) {
545 m_defaultZoom = math_clamp(zoom, WaveformWidgetRenderer::s_waveformMinZoom,
546 WaveformWidgetRenderer::s_waveformMaxZoom);
547 if (m_config) {
548 m_config->set(ConfigKey("[Waveform]","DefaultZoom"), ConfigValue(m_defaultZoom));
549 }
550
551 for (const auto& holder : m_waveformWidgetHolders) {
552 holder.m_waveformViewer->setZoom(m_defaultZoom);
553 }
554 }
555
setZoomSync(bool sync)556 void WaveformWidgetFactory::setZoomSync(bool sync) {
557 m_zoomSync = sync;
558 if (m_config) {
559 m_config->set(ConfigKey("[Waveform]","ZoomSynchronization"), ConfigValue(m_zoomSync));
560 }
561
562 if (m_waveformWidgetHolders.size() == 0) {
563 return;
564 }
565
566 double refZoom = m_waveformWidgetHolders[0].m_waveformWidget->getZoomFactor();
567 for (const auto& holder : m_waveformWidgetHolders) {
568 holder.m_waveformViewer->setZoom(refZoom);
569 }
570 }
571
setDisplayBeatGridAlpha(int alpha)572 void WaveformWidgetFactory::setDisplayBeatGridAlpha(int alpha) {
573 m_beatGridAlpha = alpha;
574 if (m_waveformWidgetHolders.size() == 0) {
575 return;
576 }
577
578 for (const auto& holder : m_waveformWidgetHolders) {
579 holder.m_waveformWidget->setDisplayBeatGridAlpha(m_beatGridAlpha);
580 }
581 }
582
setVisualGain(FilterIndex index,double gain)583 void WaveformWidgetFactory::setVisualGain(FilterIndex index, double gain) {
584 m_visualGain[index] = gain;
585 if (m_config) {
586 m_config->set(ConfigKey("[Waveform]","VisualGain_" + QString::number(index)), QString::number(m_visualGain[index]));
587 }
588 }
589
getVisualGain(FilterIndex index) const590 double WaveformWidgetFactory::getVisualGain(FilterIndex index) const {
591 return m_visualGain[index];
592 }
593
setOverviewNormalized(bool normalize)594 void WaveformWidgetFactory::setOverviewNormalized(bool normalize) {
595 m_overviewNormalized = normalize;
596 if (m_config) {
597 m_config->set(ConfigKey("[Waveform]","OverviewNormalized"), ConfigValue(m_overviewNormalized));
598 }
599 }
600
setPlayMarkerPosition(double position)601 void WaveformWidgetFactory::setPlayMarkerPosition(double position) {
602 //qDebug() << "setPlayMarkerPosition, position=" << position;
603 m_playMarkerPosition = position;
604 if (m_config) {
605 m_config->setValue(ConfigKey("[Waveform]", "PlayMarkerPosition"), m_playMarkerPosition);
606 }
607
608 for (const auto& holder : m_waveformWidgetHolders) {
609 holder.m_waveformWidget->setPlayMarkerPosition(m_playMarkerPosition);
610 }
611 }
612
notifyZoomChange(WWaveformViewer * viewer)613 void WaveformWidgetFactory::notifyZoomChange(WWaveformViewer* viewer) {
614 WaveformWidgetAbstract* pWaveformWidget = viewer->getWaveformWidget();
615 if (pWaveformWidget != nullptr && isZoomSync()) {
616 //qDebug() << "WaveformWidgetFactory::notifyZoomChange";
617 double refZoom = pWaveformWidget->getZoomFactor();
618
619 for (std::size_t i = 0; i < m_waveformWidgetHolders.size(); ++i) {
620 WaveformWidgetHolder& holder = m_waveformWidgetHolders[i];
621 if (holder.m_waveformViewer != viewer) {
622 holder.m_waveformViewer->setZoom(refZoom);
623 }
624 }
625 }
626 }
627
render()628 void WaveformWidgetFactory::render() {
629 ScopedTimer t("WaveformWidgetFactory::render() %1waveforms",
630 static_cast<int>(m_waveformWidgetHolders.size()));
631
632 //int paintersSetupTime0 = 0;
633 //int paintersSetupTime1 = 0;
634
635 //qDebug() << "render()" << m_vsyncThread->elapsed();
636
637 if (!m_skipRender) {
638 if (m_type) { // no regular updates for an empty waveform
639 // next rendered frame is displayed after next buffer swap and than after VSync
640 QVarLengthArray<bool, 10> shouldRenderWaveforms(
641 static_cast<int>(m_waveformWidgetHolders.size()));
642 for (decltype(m_waveformWidgetHolders)::size_type i = 0;
643 i < m_waveformWidgetHolders.size();
644 i++) {
645 WaveformWidgetAbstract* pWaveformWidget = m_waveformWidgetHolders[i].m_waveformWidget;
646 // Don't bother doing the pre-render work if we aren't going to
647 // render this widget.
648 bool shouldRender = shouldRenderWaveform(pWaveformWidget);
649 shouldRenderWaveforms[i] = shouldRender;
650 if (!shouldRender) {
651 continue;
652 }
653 // Calculate play position for the new Frame in following run
654 pWaveformWidget->preRender(m_vsyncThread);
655 }
656 //qDebug() << "prerender" << m_vsyncThread->elapsed();
657
658 // It may happen that there is an artificially delayed due to
659 // anti tearing driver settings
660 // all render commands are delayed until the swap from the previous run is executed
661 for (decltype(m_waveformWidgetHolders)::size_type i = 0;
662 i < m_waveformWidgetHolders.size();
663 i++) {
664 WaveformWidgetAbstract* pWaveformWidget = m_waveformWidgetHolders[i].m_waveformWidget;
665 if (!shouldRenderWaveforms[i]) {
666 continue;
667 }
668 pWaveformWidget->render();
669 //qDebug() << "render" << i << m_vsyncThread->elapsed();
670 }
671 }
672
673 // WSpinnys are also double-buffered QGLWidgets, like all the waveform
674 // renderers. Render all the WSpinny widgets now.
675 emit renderSpinnies(m_vsyncThread);
676
677 // Notify all other waveform-like widgets (e.g. WSpinny's) that they should
678 // update.
679 //int t1 = m_vsyncThread->elapsed();
680 emit waveformUpdateTick();
681 //qDebug() << "emit" << m_vsyncThread->elapsed() - t1;
682
683 m_frameCnt += 1.0f;
684 mixxx::Duration timeCnt = m_time.elapsed();
685 if (timeCnt > mixxx::Duration::fromSeconds(1)) {
686 m_time.start();
687 m_frameCnt = m_frameCnt * 1000 / timeCnt.toIntegerMillis(); // latency correction
688 emit waveformMeasured(m_frameCnt, m_vsyncThread->droppedFrames());
689 m_frameCnt = 0.0;
690 }
691 }
692
693 m_pVisualsManager->process(m_endOfTrackWarningTime);
694 m_pGuiTick->process();
695
696 //qDebug() << "refresh end" << m_vsyncThread->elapsed();
697 m_vsyncThread->vsyncSlotFinished();
698 }
699
swap()700 void WaveformWidgetFactory::swap() {
701 ScopedTimer t("WaveformWidgetFactory::swap() %1waveforms",
702 static_cast<int>(m_waveformWidgetHolders.size()));
703
704 // Do this in an extra slot to be sure to hit the desired interval
705 if (!m_skipRender) {
706 if (m_type) { // no regular updates for an empty waveform
707 // Show rendered buffer from last render() run
708 //qDebug() << "swap() start" << m_vsyncThread->elapsed();
709 for (const auto& holder : m_waveformWidgetHolders) {
710 WaveformWidgetAbstract* pWaveformWidget = holder.m_waveformWidget;
711
712 // Don't swap invalid / invisible widgets or widgets with an
713 // unexposed window. Prevents continuous log spew of
714 // "QOpenGLContext::swapBuffers() called with non-exposed
715 // window, behavior is undefined" on Qt5. See Bug #1779487.
716 if (!shouldRenderWaveform(pWaveformWidget)) {
717 continue;
718 }
719 QGLWidget* glw = qobject_cast<QGLWidget*>(pWaveformWidget->getWidget());
720 if (glw != nullptr) {
721 if (glw->context() != QGLContext::currentContext()) {
722 glw->makeCurrent();
723 }
724 glw->swapBuffers();
725 }
726 //qDebug() << "swap x" << m_vsyncThread->elapsed();
727 }
728 }
729 // WSpinnys are also double-buffered QGLWidgets, like all the waveform
730 // renderers. Swap all the WSpinny widgets now.
731 emit swapSpinnies();
732 }
733 //qDebug() << "swap end" << m_vsyncThread->elapsed();
734 m_vsyncThread->vsyncSlotFinished();
735 }
736
autoChooseWidgetType() const737 WaveformWidgetType::Type WaveformWidgetFactory::autoChooseWidgetType() const {
738 if (m_openGlAvailable) {
739 if (m_openGLShaderAvailable) {
740 return WaveformWidgetType::GLSLRGBWaveform;
741 } else {
742 return WaveformWidgetType::GLRGBWaveform;
743 }
744 }
745 return WaveformWidgetType::RGBWaveform;
746 }
747
evaluateWidgets()748 void WaveformWidgetFactory::evaluateWidgets() {
749 m_waveformWidgetHandles.clear();
750 for (int type = 0; type < WaveformWidgetType::Count_WaveformwidgetType; type++) {
751 QString widgetName;
752 bool useOpenGl;
753 bool useOpenGles;
754 bool useOpenGLShaders;
755 bool developerOnly;
756
757 switch(type) {
758 case WaveformWidgetType::EmptyWaveform:
759 widgetName = EmptyWaveformWidget::getWaveformWidgetName();
760 useOpenGl = EmptyWaveformWidget::useOpenGl();
761 useOpenGles = EmptyWaveformWidget::useOpenGles();
762 useOpenGLShaders = EmptyWaveformWidget::useOpenGLShaders();
763 developerOnly = EmptyWaveformWidget::developerOnly();
764 break;
765 case WaveformWidgetType::SoftwareSimpleWaveform:
766 continue; // //TODO(vrince):
767 case WaveformWidgetType::SoftwareWaveform:
768 #ifdef __APPLE__
769 // Don't offer the simple renderers on macOS, they do not work with skins
770 // that load GL widgets (spinnies, waveforms) in singletons.
771 // Also excluded in enum WaveformWidgetType
772 // https://bugs.launchpad.net/bugs/1928772
773 continue;
774 #else
775 widgetName = SoftwareWaveformWidget::getWaveformWidgetName();
776 useOpenGl = SoftwareWaveformWidget::useOpenGl();
777 useOpenGles = SoftwareWaveformWidget::useOpenGles();
778 useOpenGLShaders = SoftwareWaveformWidget::useOpenGLShaders();
779 developerOnly = SoftwareWaveformWidget::developerOnly();
780 break;
781 #endif
782 case WaveformWidgetType::HSVWaveform:
783 #ifdef __APPLE__
784 continue;
785 #else
786 widgetName = HSVWaveformWidget::getWaveformWidgetName();
787 useOpenGl = HSVWaveformWidget::useOpenGl();
788 useOpenGles = HSVWaveformWidget::useOpenGles();
789 useOpenGLShaders = HSVWaveformWidget::useOpenGLShaders();
790 developerOnly = HSVWaveformWidget::developerOnly();
791 break;
792 #endif
793 case WaveformWidgetType::RGBWaveform:
794 #ifdef __APPLE__
795 continue;
796 #else
797 widgetName = RGBWaveformWidget::getWaveformWidgetName();
798 useOpenGl = RGBWaveformWidget::useOpenGl();
799 useOpenGles = RGBWaveformWidget::useOpenGles();
800 useOpenGLShaders = RGBWaveformWidget::useOpenGLShaders();
801 developerOnly = RGBWaveformWidget::developerOnly();
802 break;
803 #endif
804 case WaveformWidgetType::QtSimpleWaveform:
805 widgetName = QtSimpleWaveformWidget::getWaveformWidgetName();
806 useOpenGl = QtSimpleWaveformWidget::useOpenGl();
807 useOpenGles = QtSimpleWaveformWidget::useOpenGles();
808 useOpenGLShaders = QtSimpleWaveformWidget::useOpenGLShaders();
809 developerOnly = QtSimpleWaveformWidget::developerOnly();
810 break;
811 case WaveformWidgetType::QtWaveform:
812 widgetName = QtWaveformWidget::getWaveformWidgetName();
813 useOpenGl = QtWaveformWidget::useOpenGl();
814 useOpenGles = QtWaveformWidget::useOpenGles();
815 useOpenGLShaders = QtWaveformWidget::useOpenGLShaders();
816 developerOnly = QtWaveformWidget::developerOnly();
817 break;
818 case WaveformWidgetType::GLSimpleWaveform:
819 widgetName = GLSimpleWaveformWidget::getWaveformWidgetName();
820 useOpenGl = GLSimpleWaveformWidget::useOpenGl();
821 useOpenGles = GLSimpleWaveformWidget::useOpenGles();
822 useOpenGLShaders = GLSimpleWaveformWidget::useOpenGLShaders();
823 developerOnly = GLSimpleWaveformWidget::developerOnly();
824 break;
825 case WaveformWidgetType::GLFilteredWaveform:
826 widgetName = GLWaveformWidget::getWaveformWidgetName();
827 useOpenGl = GLWaveformWidget::useOpenGl();
828 useOpenGles = GLWaveformWidget::useOpenGles();
829 useOpenGLShaders = GLWaveformWidget::useOpenGLShaders();
830 developerOnly = GLWaveformWidget::developerOnly();
831 break;
832 case WaveformWidgetType::GLSLFilteredWaveform:
833 widgetName = GLSLFilteredWaveformWidget::getWaveformWidgetName();
834 useOpenGl = GLSLFilteredWaveformWidget::useOpenGl();
835 useOpenGles = GLSLFilteredWaveformWidget::useOpenGles();
836 useOpenGLShaders = GLSLFilteredWaveformWidget::useOpenGLShaders();
837 developerOnly = GLSLFilteredWaveformWidget::developerOnly();
838 break;
839 case WaveformWidgetType::GLSLRGBWaveform:
840 widgetName = GLSLRGBWaveformWidget::getWaveformWidgetName();
841 useOpenGl = GLSLRGBWaveformWidget::useOpenGl();
842 useOpenGles = GLSLRGBWaveformWidget::useOpenGles();
843 useOpenGLShaders = GLSLRGBWaveformWidget::useOpenGLShaders();
844 developerOnly = GLSLRGBWaveformWidget::developerOnly();
845 break;
846 case WaveformWidgetType::GLVSyncTest:
847 widgetName = GLVSyncTestWidget::getWaveformWidgetName();
848 useOpenGl = GLVSyncTestWidget::useOpenGl();
849 useOpenGles = GLVSyncTestWidget::useOpenGles();
850 useOpenGLShaders = GLVSyncTestWidget::useOpenGLShaders();
851 developerOnly = GLVSyncTestWidget::developerOnly();
852 break;
853 case WaveformWidgetType::GLRGBWaveform:
854 widgetName = GLRGBWaveformWidget::getWaveformWidgetName();
855 useOpenGl = GLRGBWaveformWidget::useOpenGl();
856 useOpenGles = GLRGBWaveformWidget::useOpenGles();
857 useOpenGLShaders = GLRGBWaveformWidget::useOpenGLShaders();
858 developerOnly = GLRGBWaveformWidget::developerOnly();
859 break;
860 case WaveformWidgetType::QtVSyncTest:
861 widgetName = QtVSyncTestWidget::getWaveformWidgetName();
862 useOpenGl = QtVSyncTestWidget::useOpenGl();
863 useOpenGles = QtVSyncTestWidget::useOpenGles();
864 useOpenGLShaders = QtVSyncTestWidget::useOpenGLShaders();
865 developerOnly = QtVSyncTestWidget::developerOnly();
866 break;
867 case WaveformWidgetType::QtHSVWaveform:
868 widgetName = QtHSVWaveformWidget::getWaveformWidgetName();
869 useOpenGl = QtHSVWaveformWidget::useOpenGl();
870 useOpenGles = QtHSVWaveformWidget::useOpenGles();
871 useOpenGLShaders = QtHSVWaveformWidget::useOpenGLShaders();
872 developerOnly = QtHSVWaveformWidget::developerOnly();
873 break;
874 case WaveformWidgetType::QtRGBWaveform:
875 widgetName = QtRGBWaveformWidget::getWaveformWidgetName();
876 useOpenGl = QtRGBWaveformWidget::useOpenGl();
877 useOpenGles = QtRGBWaveformWidget::useOpenGles();
878 useOpenGLShaders = QtRGBWaveformWidget::useOpenGLShaders();
879 developerOnly = QtRGBWaveformWidget::developerOnly();
880 break;
881 default:
882 DEBUG_ASSERT(!"Unexpected WaveformWidgetType");
883 continue;
884 }
885
886 bool active = true;
887 if (isOpenGlAvailable()) {
888 if (useOpenGles && !useOpenGl) {
889 active = false;
890 } else if (useOpenGLShaders && !isOpenGlShaderAvailable()) {
891 active = false;
892 } else {
893 if (useOpenGLShaders) {
894 widgetName += " " + tr("(GLSL)");
895 } else if (useOpenGl) {
896 widgetName += " " + tr("(GL)");
897 }
898 }
899 } else if (isOpenGlesAvailable()) {
900 if (useOpenGl && !useOpenGles) {
901 active = false;
902 } else if (useOpenGLShaders && !isOpenGlShaderAvailable()) {
903 active = false;
904 } else {
905 if (useOpenGLShaders) {
906 widgetName += " " + tr("(GLSL ES)");
907 } else if (useOpenGles) {
908 widgetName += " " + tr("(GL ES)");
909 }
910 }
911 } else {
912 // No sufficiant GL supptor
913 if (useOpenGles || useOpenGl || useOpenGLShaders) {
914 active = false;
915 }
916 }
917
918 if (developerOnly && !CmdlineArgs::Instance().getDeveloper()) {
919 active = false;
920 }
921
922 if (active) {
923 // add new handle for each available widget type
924 WaveformWidgetAbstractHandle handle;
925 handle.m_displayString = widgetName;
926 handle.m_type = (WaveformWidgetType::Type)type;
927
928 m_waveformWidgetHandles.push_back(handle);
929 }
930 }
931 }
932
createWaveformWidget(WaveformWidgetType::Type type,WWaveformViewer * viewer)933 WaveformWidgetAbstract* WaveformWidgetFactory::createWaveformWidget(
934 WaveformWidgetType::Type type, WWaveformViewer* viewer) {
935 WaveformWidgetAbstract* widget = nullptr;
936 if (viewer) {
937 if (CmdlineArgs::Instance().getSafeMode()) {
938 type = WaveformWidgetType::EmptyWaveform;
939 }
940
941 switch(type) {
942 case WaveformWidgetType::SoftwareWaveform:
943 widget = new SoftwareWaveformWidget(viewer->getGroup(), viewer);
944 break;
945 case WaveformWidgetType::HSVWaveform:
946 widget = new HSVWaveformWidget(viewer->getGroup(), viewer);
947 break;
948 case WaveformWidgetType::RGBWaveform:
949 widget = new RGBWaveformWidget(viewer->getGroup(), viewer);
950 break;
951 case WaveformWidgetType::QtSimpleWaveform:
952 widget = new QtSimpleWaveformWidget(viewer->getGroup(), viewer);
953 break;
954 case WaveformWidgetType::QtWaveform:
955 widget = new QtWaveformWidget(viewer->getGroup(), viewer);
956 break;
957 case WaveformWidgetType::GLSimpleWaveform:
958 widget = new GLSimpleWaveformWidget(viewer->getGroup(), viewer);
959 break;
960 case WaveformWidgetType::GLFilteredWaveform:
961 widget = new GLWaveformWidget(viewer->getGroup(), viewer);
962 break;
963 case WaveformWidgetType::GLRGBWaveform:
964 widget = new GLRGBWaveformWidget(viewer->getGroup(), viewer);
965 break;
966 case WaveformWidgetType::GLSLFilteredWaveform:
967 widget = new GLSLFilteredWaveformWidget(viewer->getGroup(), viewer);
968 break;
969 case WaveformWidgetType::GLSLRGBWaveform:
970 widget = new GLSLRGBWaveformWidget(viewer->getGroup(), viewer);
971 break;
972 case WaveformWidgetType::GLVSyncTest:
973 widget = new GLVSyncTestWidget(viewer->getGroup(), viewer);
974 break;
975 case WaveformWidgetType::QtVSyncTest:
976 widget = new QtVSyncTestWidget(viewer->getGroup(), viewer);
977 break;
978 case WaveformWidgetType::QtHSVWaveform:
979 widget = new QtHSVWaveformWidget(viewer->getGroup(), viewer);
980 break;
981 case WaveformWidgetType::QtRGBWaveform:
982 widget = new QtRGBWaveformWidget(viewer->getGroup(), viewer);
983 break;
984 default:
985 //case WaveformWidgetType::SoftwareSimpleWaveform: TODO: (vrince)
986 //case WaveformWidgetType::EmptyWaveform:
987 widget = new EmptyWaveformWidget(viewer->getGroup(), viewer);
988 break;
989 }
990 widget->castToQWidget();
991 if (!widget->isValid()) {
992 qWarning() << "failed to init WafeformWidget" << type << "fall back to \"Empty\"";
993 delete widget;
994 widget = new EmptyWaveformWidget(viewer->getGroup(), viewer);
995 widget->castToQWidget();
996 if (!widget->isValid()) {
997 qWarning() << "failed to init EmptyWaveformWidget";
998 delete widget;
999 widget = nullptr;
1000 }
1001 }
1002 }
1003 return widget;
1004 }
1005
findIndexOf(WWaveformViewer * viewer) const1006 int WaveformWidgetFactory::findIndexOf(WWaveformViewer* viewer) const {
1007 for (int i = 0; i < (int)m_waveformWidgetHolders.size(); i++) {
1008 if (m_waveformWidgetHolders[i].m_waveformViewer == viewer) {
1009 return i;
1010 }
1011 }
1012 return -1;
1013 }
1014
startVSync(GuiTick * pGuiTick,VisualsManager * pVisualsManager)1015 void WaveformWidgetFactory::startVSync(GuiTick* pGuiTick, VisualsManager* pVisualsManager) {
1016 m_pGuiTick = pGuiTick;
1017 m_pVisualsManager = pVisualsManager;
1018 m_vsyncThread = new VSyncThread(this);
1019 m_vsyncThread->setObjectName(QStringLiteral("VSync"));
1020 m_vsyncThread->setVSyncType(m_vSyncType);
1021 m_vsyncThread->setSyncIntervalTimeMicros(static_cast<int>(1e6 / m_frameRate));
1022
1023 connect(m_vsyncThread,
1024 &VSyncThread::vsyncRender,
1025 this,
1026 &WaveformWidgetFactory::render);
1027 connect(m_vsyncThread,
1028 &VSyncThread::vsyncSwap,
1029 this,
1030 &WaveformWidgetFactory::swap);
1031
1032 m_vsyncThread->start(QThread::NormalPriority);
1033 }
1034
getAvailableVSyncTypes(QList<QPair<int,QString>> * pList)1035 void WaveformWidgetFactory::getAvailableVSyncTypes(QList<QPair<int, QString > >* pList) {
1036 m_vsyncThread->getAvailableVSyncTypes(pList);
1037 }
1038
findTypeFromHandleIndex(int index)1039 WaveformWidgetType::Type WaveformWidgetFactory::findTypeFromHandleIndex(int index) {
1040 WaveformWidgetType::Type type = WaveformWidgetType::Count_WaveformwidgetType;
1041 if (index >= 0 && index < m_waveformWidgetHandles.size()) {
1042 type = m_waveformWidgetHandles[index].m_type;
1043 }
1044 return type;
1045 }
1046
findHandleIndexFromType(WaveformWidgetType::Type type)1047 int WaveformWidgetFactory::findHandleIndexFromType(WaveformWidgetType::Type type) {
1048 int index = -1;
1049 for (int i = 0; i < m_waveformWidgetHandles.size(); i++) {
1050 WaveformWidgetAbstractHandle& handle = m_waveformWidgetHandles[i];
1051 if (handle.m_type == type) {
1052 index = i;
1053 }
1054 }
1055 return index;
1056 }
1057