Merge lp:~mixxxdevelopers/mixxx/waveform-dejerk into lp:~mixxxdevelopers/mixxx/trunk

Proposed by Daniel Schürmann
Status: Needs review
Proposed branch: lp:~mixxxdevelopers/mixxx/waveform-dejerk
Merge into: lp:~mixxxdevelopers/mixxx/trunk
Diff against target: 3371 lines (+1344/-530)
50 files modified
mixxx/build/depends.py (+4/-0)
mixxx/src/controlobjectbase.h (+147/-0)
mixxx/src/dlgprefcontrols.cpp (+16/-23)
mixxx/src/dlgprefcontrols.h (+1/-6)
mixxx/src/engine/bpmcontrol.cpp (+3/-2)
mixxx/src/engine/enginebuffer.cpp (+9/-10)
mixxx/src/engine/enginebuffer.h (+3/-2)
mixxx/src/main.cpp (+9/-0)
mixxx/src/mixxx.cpp (+1/-3)
mixxx/src/sounddeviceportaudio.cpp (+2/-0)
mixxx/src/visualplayposition.cpp (+109/-0)
mixxx/src/visualplayposition.h (+57/-0)
mixxx/src/waveform/renderers/glvsynctestrenderer.cpp (+133/-0)
mixxx/src/waveform/renderers/glvsynctestrenderer.h (+19/-0)
mixxx/src/waveform/renderers/waveformrenderbeat.cpp (+1/-1)
mixxx/src/waveform/renderers/waveformrendererendoftrack.cpp (+16/-2)
mixxx/src/waveform/renderers/waveformrendererendoftrack.h (+2/-1)
mixxx/src/waveform/renderers/waveformrendererhsv.cpp (+0/-177)
mixxx/src/waveform/renderers/waveformrendererhsv.h (+0/-21)
mixxx/src/waveform/renderers/waveformrendererpreroll.cpp (+5/-3)
mixxx/src/waveform/renderers/waveformrendermark.cpp (+2/-2)
mixxx/src/waveform/renderers/waveformrendermarkrange.cpp (+2/-2)
mixxx/src/waveform/renderers/waveformwidgetrenderer.cpp (+50/-50)
mixxx/src/waveform/renderers/waveformwidgetrenderer.h (+7/-4)
mixxx/src/waveform/vsyncthread.cpp (+179/-0)
mixxx/src/waveform/vsyncthread.h (+109/-0)
mixxx/src/waveform/waveformwidgetfactory.cpp (+160/-55)
mixxx/src/waveform/waveformwidgetfactory.h (+27/-16)
mixxx/src/waveform/widgets/emptywaveformwidget.cpp (+6/-0)
mixxx/src/waveform/widgets/emptywaveformwidget.h (+2/-1)
mixxx/src/waveform/widgets/glsimplewaveformwidget.cpp (+19/-4)
mixxx/src/waveform/widgets/glsimplewaveformwidget.h (+6/-5)
mixxx/src/waveform/widgets/glslwaveformwidget.cpp (+23/-3)
mixxx/src/waveform/widgets/glslwaveformwidget.h (+7/-5)
mixxx/src/waveform/widgets/glvsynctestwidget.cpp (+75/-0)
mixxx/src/waveform/widgets/glvsynctestwidget.h (+30/-0)
mixxx/src/waveform/widgets/glwaveformwidget.cpp (+18/-4)
mixxx/src/waveform/widgets/glwaveformwidget.h (+5/-4)
mixxx/src/waveform/widgets/hsvwaveformwidget.cpp (+0/-41)
mixxx/src/waveform/widgets/hsvwaveformwidget.h (+0/-29)
mixxx/src/waveform/widgets/qtsimplewaveformwidget.cpp (+19/-4)
mixxx/src/waveform/widgets/qtsimplewaveformwidget.h (+6/-5)
mixxx/src/waveform/widgets/qtwaveformwidget.cpp (+19/-4)
mixxx/src/waveform/widgets/qtwaveformwidget.h (+6/-5)
mixxx/src/waveform/widgets/softwarewaveformwidget.h (+5/-5)
mixxx/src/waveform/widgets/waveformwidgetabstract.cpp (+8/-15)
mixxx/src/waveform/widgets/waveformwidgetabstract.h (+5/-4)
mixxx/src/waveform/widgets/waveformwidgettype.h (+3/-2)
mixxx/src/widget/wspinny.cpp (+7/-8)
mixxx/src/widget/wspinny.h (+2/-2)
To merge this branch: bzr merge lp:~mixxxdevelopers/mixxx/waveform-dejerk
Reviewer Review Type Date Requested Status
Mixxx Development Team Pending
Review via email: mp+156977@code.launchpad.net

Description of the change

This branch contains the first transition of waveform dejerking.
It introduces a timestamped visual play position, a vsync thread for precise timing and the infrastructure to allow advanced vsync strategies.
In this merge, is only the simple pure timer sync strategy included for not making this merge too big.
The improvement is notable but the waveforms are still jerking.
A vsync test waveform type is included an is available by starting Mixxx with --developer.

--

The Implementation tries to display the right waveform picture in the right moment.
This is archived by the VisualPlayPosition Class. It is something like a time stamped Control object, using he new atomic ControlObjectBase for bypassing the delays from the Qt Mesasage Queue and the Sync Thread from the current Control Object implementation.

This way we get rid of unpredictable delays and mixed up message order during heavy load.

The time stamp ov the Visual Play position is generated by the Portaudio timeInfo VisualPlayPosition::setTimeInfo(timeInfo);
The Play position for the waveform is adjusted for the actual display time in
VisualPlayPosition::getAt

The display frame timing is done by a separate Thread. This is required because the Qt Timer event is not super precise. This thread controls the rendering process by using sleep() and semaphores.

Currently it is not using Time stamp information from the driver. I have relay good results with specific set-ups, but it is also suffering from driver quality in other set-ups. So I have removed this from the current merge request but I am planning to add additional advanced dejerking strategies using openGL from daschuers_trunk later.

To post a comment you must log in.
Revision history for this message
jus (jus) wrote :

FYI branch needs the diff from https://bazaar.launchpad.net/~mixxxdevelopers/mixxx/release-1.11.x/revision/3836 in order to compile on OSX. Going to test branch on MacBookPro8,1 and iMac13,1

3344. By Daniel Schürmann

merged from lp:mixxx

Revision history for this message
Daniel Schürmann (daschuer) wrote :

Thank you, for testing!

Just merged with lp:mixxx, so it should now build with OSX.

Do you have any results?

Unmerged revisions

3344. By Daniel Schürmann

merged from lp:mixxx

3343. By Daniel Schürmann

merged from lp:mixxx

3342. By Daniel Schürmann

clean up finished

3341. By Daniel Schürmann

code clean up

3340. By Daniel Schürmann

merged from lp:mixxx

3339. By Daniel Schürmann

fixed crash

3338. By Daniel Schürmann

compilable but crashing

3337. By Daniel Schürmann

merged ../daschuers_trunk/mixxx/src/waveform/

3336. By Daniel Schürmann

merged from lp:mixxx

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'mixxx/build/depends.py'
2--- mixxx/build/depends.py 2013-02-09 00:49:59 +0000
3+++ mixxx/build/depends.py 2013-05-01 22:08:27 +0000
4@@ -632,6 +632,7 @@
5 "waveform/waveform.cpp",
6 "waveform/waveformfactory.cpp",
7 "waveform/waveformwidgetfactory.cpp",
8+ "waveform/vsyncthread.cpp",
9 "waveform/renderers/waveformwidgetrenderer.cpp",
10 "waveform/renderers/waveformrendererabstract.cpp",
11 "waveform/renderers/waveformrenderbackground.cpp",
12@@ -648,6 +649,7 @@
13 "waveform/renderers/glwaveformrendererfilteredsignal.cpp",
14 "waveform/renderers/glwaveformrenderersimplesignal.cpp",
15 "waveform/renderers/glslwaveformrenderersignal.cpp",
16+ "waveform/renderers/glvsynctestrenderer.cpp",
17
18 "waveform/renderers/waveformsignalcolors.cpp",
19
20@@ -664,6 +666,7 @@
21 "waveform/widgets/qtsimplewaveformwidget.cpp",
22 "waveform/widgets/glwaveformwidget.cpp",
23 "waveform/widgets/glsimplewaveformwidget.cpp",
24+ "waveform/widgets/glvsynctestwidget.cpp",
25
26 "waveform/widgets/glslwaveformwidget.cpp",
27
28@@ -696,6 +699,7 @@
29 "soundmanagerutil.cpp",
30 "dlgprefrecord.cpp",
31 "playerinfo.cpp",
32+ "visualplayposition.cpp",
33
34 "recording/enginerecord.cpp",
35 "recording/encoder.cpp",
36
37=== added file 'mixxx/src/controlobjectbase.h'
38--- mixxx/src/controlobjectbase.h 1970-01-01 00:00:00 +0000
39+++ mixxx/src/controlobjectbase.h 2013-05-01 22:08:27 +0000
40@@ -0,0 +1,147 @@
41+
42+#ifndef CONTROLOBJECTBASE_H_
43+#define CONTROLOBJECTBASE_H_
44+
45+#include <QAtomicInt>
46+#include <QObject>
47+
48+static const int cReaderSlotCnt = 7;
49+
50+template<typename T>
51+class ControlObjectRingValue {
52+ public:
53+ ControlObjectRingValue()
54+ : m_value(T()),
55+ m_readerSlots(cReaderSlotCnt) {
56+ }
57+
58+ int tryGet(T* value) {
59+ // Read while consuming one readerSlot
60+ bool originalSlots = m_readerSlots.fetchAndAddAcquire(-1);
61+ if (originalSlots) {
62+ *value = m_value;
63+ }
64+ (void)m_readerSlots.fetchAndAddRelease(1);
65+ return originalSlots;
66+ }
67+
68+ bool trySet(const T& value) {
69+ // try to lock this element entirely for reading
70+ if (m_readerSlots.testAndSetAcquire(cReaderSlotCnt, 0)) {
71+ m_value = value;
72+ m_readerSlots.fetchAndAddRelease(cReaderSlotCnt);
73+ return true;
74+ }
75+ return false;
76+ }
77+
78+ private:
79+ T m_value;
80+ QAtomicInt m_readerSlots;
81+};
82+
83+// Common implementation for all Types
84+template<typename T, bool ATOMIC = false>
85+class ControlObjectValue {
86+ public:
87+ inline T getValue() {
88+ T value = T();
89+ unsigned int index = (unsigned int)m_readIndex
90+ % (cReaderSlotCnt + 1);
91+ while (m_ring[index].tryGet(&value) == 0) {
92+ // We are here if
93+ // 1) there are more then cReaderSlotCnt reader (get) reading the same value or
94+ // 2) the formerly current value is locked by a writer
95+ // Case 1 is prevented by enough reader slots and schould not happen
96+ // Case 2 happens when the a reader is delayed after reading the
97+ // m_currentIndex and the writers have written cReaderSlotCnt times so that the
98+ // formally current value is locked again for writing.
99+ // In both cases reading the less recent value will fix it.
100+ index = (index - 1) % (cReaderSlotCnt + 1);
101+ }
102+ return value;
103+ }
104+
105+ inline void setValue(const T& value) {
106+ // Test if we can read atomic
107+ // This test is const and will be mad only at compile time
108+ unsigned int index;
109+ do {
110+ index = (unsigned int)m_writeIndex.fetchAndAddAcquire(1)
111+ % (cReaderSlotCnt + 1);
112+ // This will be repeated if the value is locked
113+ // 1) by an other writer writing at the same time or
114+ // 2) a delayed reader is still blocking the formerly current value
115+ // In both cases writing to the next value will fix it.
116+ } while (!m_ring[index].trySet(value));
117+ m_readIndex = (int)index;
118+ }
119+
120+ protected:
121+ ControlObjectValue()
122+ : m_readIndex(0),
123+ m_writeIndex(1) {
124+ }
125+
126+ private:
127+ ControlObjectRingValue<T> m_ring[cReaderSlotCnt+1];
128+ QAtomicInt m_readIndex;
129+ QAtomicInt m_writeIndex;
130+};
131+
132+// Specialized Template for atomic types
133+template<typename T>
134+class ControlObjectValue<T, true> {
135+ public:
136+ inline T getValue() {
137+ return m_value;
138+ }
139+
140+ inline void setValue(const T& value) {
141+ m_value = value;
142+ }
143+
144+ protected:
145+ ControlObjectValue()
146+ : m_value(T()) {
147+ }
148+
149+ private:
150+ T m_value;
151+};
152+
153+// Note: Qt does not support templates for signal and slots
154+// So the typified ControlObject has to handle the Event Queue connections
155+template<typename T>
156+class ControlObjectBase
157+ : public ControlObjectValue<T, sizeof(T) <= sizeof(void*)> {
158+ public:
159+ ControlObjectBase()
160+ : ControlObjectValue<T, sizeof(T) <= sizeof(void*)>() {
161+ }
162+};
163+
164+
165+template<typename T>
166+class ControlObjectThreadBase {
167+ public:
168+ ControlObjectThreadBase(ControlObjectBase<T>* pControlObject)
169+ : m_pControlObject(pControlObject) {
170+ }
171+ virtual ~ControlObjectThreadBase();
172+
173+ inline T get() const {
174+ return m_pControlObject->get();
175+ }
176+
177+ inline void set(const T& value) {
178+ return m_pControlObject->get();
179+ }
180+
181+ private:
182+ ControlObjectBase<T>* m_pControlObject;
183+};
184+
185+
186+#endif // CONTROLOBJECTBASE_H_
187+
188
189=== modified file 'mixxx/src/dlgprefcontrols.cpp'
190--- mixxx/src/dlgprefcontrols.cpp 2013-01-27 23:04:37 +0000
191+++ mixxx/src/dlgprefcontrols.cpp 2013-05-01 22:08:27 +0000
192@@ -44,7 +44,6 @@
193 ConfigObject<ConfigValue> * pConfig)
194 : QWidget(parent) {
195 m_pConfig = pConfig;
196- m_timer = -1;
197 m_mixxx = mixxx;
198 m_pSkinLoader = pSkinLoader;
199 m_pPlayerManager = pPlayerManager;
200@@ -597,24 +596,14 @@
201 WaveformWidgetFactory::instance()->setOverviewNormalized(normalize);
202 }
203
204-void DlgPrefControls::onShow() {
205- m_timer = startTimer(100); //refresh actual frame rate every 100 ms
206-}
207-
208-void DlgPrefControls::onHide() {
209- if (m_timer != -1) {
210- killTimer(m_timer);
211- }
212-}
213-
214-void DlgPrefControls::timerEvent(QTimerEvent * /*event*/) {
215- //Just to refresh actual framrate any time the controller is modified
216- frameRateAverage->setText(QString::number(
217- WaveformWidgetFactory::instance()->getActualFrameRate()));
218-}
219-
220-void DlgPrefControls::initWaveformControl()
221-{
222+void DlgPrefControls::slotWaveformMeasured(float frameRate, int rtErrorCnt) {
223+ frameRateAverage->setText(
224+ QString::number((double)frameRate, 'f', 2) +
225+ " e" +
226+ QString::number(rtErrorCnt));
227+}
228+
229+void DlgPrefControls::initWaveformControl() {
230 waveformTypeComboBox->clear();
231 WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();
232
233@@ -626,15 +615,17 @@
234 WaveformWidgetType::Type currentType = factory->getType();
235 int currentIndex = -1;
236
237- std::vector<WaveformWidgetAbstractHandle> handles = factory->getAvailableTypes();
238- for (unsigned int i = 0; i < handles.size(); i++) {
239+ QVector<WaveformWidgetAbstractHandle> handles = factory->getAvailableTypes();
240+ for (int i = 0; i < handles.size(); i++) {
241 waveformTypeComboBox->addItem(handles[i].getDisplayName());
242- if (handles[i].getType() == currentType)
243+ if (handles[i].getType() == currentType) {
244 currentIndex = i;
245+ }
246 }
247
248- if (currentIndex != -1)
249+ if (currentIndex != -1) {
250 waveformTypeComboBox->setCurrentIndex(currentIndex);
251+ }
252
253 frameRateSpinBox->setValue(factory->getFrameRate());
254
255@@ -671,6 +662,8 @@
256 connect(normalizeOverviewCheckBox,SIGNAL(toggled(bool)),
257 this,SLOT(slotSetNormalizeOverview(bool)));
258
259+ connect(WaveformWidgetFactory::instance(), SIGNAL(waveformMeasured(float,int)),
260+ this, SLOT(slotWaveformMeasured(float,int)));
261 }
262
263 //Returns TRUE if skin fits to screen resolution, FALSE otherwise
264
265=== modified file 'mixxx/src/dlgprefcontrols.h'
266--- mixxx/src/dlgprefcontrols.h 2013-01-27 23:04:37 +0000
267+++ mixxx/src/dlgprefcontrols.h 2013-05-01 22:08:27 +0000
268@@ -73,12 +73,7 @@
269 void slotSetVisualGainMid(double gain);
270 void slotSetVisualGainHigh(double gain);
271 void slotSetNormalizeOverview( bool normalize);
272-
273- virtual void onShow();
274- virtual void onHide();
275-
276-protected:
277- void timerEvent(QTimerEvent *);
278+ void slotWaveformMeasured(float frameRate, int rtErrorCnt);
279
280 private:
281 void initWaveformControl();
282
283=== modified file 'mixxx/src/engine/bpmcontrol.cpp'
284--- mixxx/src/engine/bpmcontrol.cpp 2013-03-31 16:56:35 +0000
285+++ mixxx/src/engine/bpmcontrol.cpp 2013-05-01 22:08:27 +0000
286@@ -8,6 +8,7 @@
287
288 #include "engine/enginebuffer.h"
289 #include "engine/bpmcontrol.h"
290+#include "visualplayposition.h"
291 #include "engine/enginechannel.h"
292 #include "engine/enginemaster.h"
293
294@@ -318,8 +319,8 @@
295 double dThisPosition = getCurrentSample();
296 double dOtherLength = ControlObject::getControl(
297 ConfigKey(pOtherEngineBuffer->getGroup(), "track_samples"))->get();
298- double dOtherEnginePlayPos = ControlObject::getControl(
299- ConfigKey(pOtherEngineBuffer->getGroup(), "visual_playposition"))->get();
300+ double dOtherEnginePlayPos =
301+ VisualPlayPosition::getVisualPlayPosition(pOtherEngineBuffer->getGroup())->getEnginePlayPos();
302 double dOtherPosition = dOtherLength * dOtherEnginePlayPos;
303
304 double dThisPrevBeat = m_pBeats->findPrevBeat(dThisPosition);
305
306=== modified file 'mixxx/src/engine/enginebuffer.cpp'
307--- mixxx/src/engine/enginebuffer.cpp 2013-04-23 18:15:21 +0000
308+++ mixxx/src/engine/enginebuffer.cpp 2013-05-01 22:08:27 +0000
309@@ -37,6 +37,7 @@
310 #include "engine/ratecontrol.h"
311 #include "engine/bpmcontrol.h"
312 #include "engine/quantizecontrol.h"
313+#include "visualplayposition.h"
314 #include "util/timer.h"
315
316 #ifdef __VINYLCONTROL__
317@@ -148,7 +149,6 @@
318 connect(m_pSlipButton, SIGNAL(valueChangedFromEngine(double)),
319 this, SLOT(slotControlSlip(double)),
320 Qt::DirectConnection);
321- m_pSlipPosition = new ControlObject(ConfigKey(m_group, "slip_playposition"));
322
323 // Actual rate (used in visuals, not for control)
324 m_rateEngine = new ControlObject(ConfigKey(m_group, "rateEngine"));
325@@ -165,8 +165,7 @@
326 Qt::DirectConnection);
327
328 // Control used to communicate ratio playpos to GUI thread
329- m_visualPlaypos = new ControlPotmeter(
330- ConfigKey(m_group, "visual_playposition"), kMinPlayposRange, kMaxPlayposRange);
331+ m_visualPlayPos = VisualPlayPosition::getVisualPlayPosition(m_group);
332
333 m_pRepeat = new ControlPushButton(ConfigKey(m_group, "repeat"));
334 m_pRepeat->setButtonMode(ControlPushButton::TOGGLE);
335@@ -251,11 +250,9 @@
336 delete m_stopButton;
337 delete m_rateEngine;
338 delete m_playposSlider;
339- delete m_visualPlaypos;
340 delete m_visualBpm;
341
342 delete m_pSlipButton;
343- delete m_pSlipPosition;
344 delete m_pRepeat;
345
346 delete m_pTrackSamples;
347@@ -384,7 +381,7 @@
348 int iTrackSampleRate,
349 int iTrackNumSamples) {
350 m_pause.lock();
351- m_visualPlaypos->set(-1);
352+ m_visualPlayPos->setInvalid();
353 m_pCurrentTrack = pTrack;
354 m_file_srate_old = iTrackSampleRate;
355 m_file_length_old = iTrackNumSamples;
356@@ -527,13 +524,11 @@
357 // TODO(rryan): Should this filepos instead be the RAMAN current
358 // position? filepos_play could be out of date.
359 m_dSlipPosition = m_filepos_play;
360- m_pSlipPosition->set(fractionalPlayposFromAbsolute(m_dSlipPosition));
361 m_dSlipRate = m_rate_old;
362 } else {
363 // TODO(owen) assuming that looping will get canceled properly
364 slotControlSeekAbs(m_dSlipPosition);
365 m_dSlipPosition = 0;
366- m_pSlipPosition->set(0);
367 }
368 }
369
370@@ -577,7 +572,6 @@
371 // Update the slipped position
372 if (m_bSlipEnabled) {
373 m_dSlipPosition += static_cast<double>(iBufferSize) * m_dSlipRate;
374- m_pSlipPosition->set(fractionalPlayposFromAbsolute(m_dSlipPosition));
375 }
376
377 // Scratching always disables keylock because keylock sounds terrible
378@@ -852,6 +846,9 @@
379 m_iSamplesCalculated += iBufferSize;
380
381 double fFractionalPlaypos = fractionalPlayposFromAbsolute(m_filepos_play);
382+ if(rate > 0 && fFractionalPlaypos == 1.0) {
383+ rate = 0;
384+ }
385
386 // Update indicators that are only updated after every
387 // sampleRate/kiUpdateRate samples processed. (e.g. playposSlider,
388@@ -874,7 +871,9 @@
389
390 // Update visual control object, this needs to be done more often than the
391 // rateEngine and playpos slider
392- m_visualPlaypos->set(fFractionalPlaypos);
393+ m_visualPlayPos->set(fFractionalPlaypos, rate,
394+ (double)iBufferSize/m_file_length_old,
395+ fractionalPlayposFromAbsolute(m_dSlipPosition));
396 }
397
398 void EngineBuffer::hintReader(const double dRate) {
399
400=== modified file 'mixxx/src/engine/enginebuffer.h'
401--- mixxx/src/engine/enginebuffer.h 2013-02-03 18:50:24 +0000
402+++ mixxx/src/engine/enginebuffer.h 2013-05-01 22:08:27 +0000
403@@ -49,6 +49,7 @@
404 class EngineBufferScaleLinear;
405 class EngineBufferScaleST;
406 class EngineWorkerScheduler;
407+class VisualPlayPosition;
408 class EngineMaster;
409
410 struct Hint;
411@@ -225,13 +226,11 @@
412 ControlObject* m_fwdButton;
413 ControlObject* m_backButton;
414 ControlPushButton* m_pSlipButton;
415- ControlObject* m_pSlipPosition;
416
417 ControlObject* m_rateEngine;
418 ControlObject* m_visualBpm;
419 ControlObject* m_pMasterRate;
420 ControlPotmeter* m_playposSlider;
421- ControlPotmeter* m_visualPlaypos;
422 ControlObject* m_pSampleRate;
423 ControlPushButton* m_pKeylock;
424
425@@ -277,6 +276,8 @@
426 CSAMPLE* m_pCrossFadeBuffer;
427 int m_iCrossFadeSamples;
428 int m_iLastBufferSize;
429+
430+ VisualPlayPosition* m_visualPlayPos;
431 };
432
433 #endif
434
435=== modified file 'mixxx/src/main.cpp'
436--- mixxx/src/main.cpp 2013-04-28 18:46:48 +0000
437+++ mixxx/src/main.cpp 2013-05-01 22:08:27 +0000
438@@ -40,6 +40,10 @@
439 #include <ladspa/ladspaloader.h>
440 #endif
441
442+#ifdef Q_WS_X11
443+#include <X11/Xlib.h>
444+#endif
445+
446 #ifdef __WINDOWS__
447 #ifdef DEBUGCONSOLE
448 #include <io.h> // Debug Console
449@@ -139,6 +143,11 @@
450
451 int main(int argc, char * argv[])
452 {
453+
454+#ifdef Q_WS_X11
455+ XInitThreads();
456+#endif
457+
458 // Check if an instance of Mixxx is already running
459 // See http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Utilities/qtsingleapplication
460
461
462=== modified file 'mixxx/src/mixxx.cpp'
463--- mixxx/src/mixxx.cpp 2013-05-01 20:29:44 +0000
464+++ mixxx/src/mixxx.cpp 2013-05-01 22:08:27 +0000
465@@ -387,6 +387,7 @@
466 this, SLOT(slotSyncControlSystem()));
467
468 WaveformWidgetFactory::create();
469+ WaveformWidgetFactory::instance()->startVSync(this);
470 WaveformWidgetFactory::instance()->setConfig(m_pConfig);
471
472 m_pSkinLoader = new SkinLoader(m_pConfig);
473@@ -1609,7 +1610,6 @@
474
475 m_pView->hide();
476
477- WaveformWidgetFactory::instance()->stop();
478 WaveformWidgetFactory::instance()->destroyWidgets();
479
480 // Workaround for changing skins while fullscreen, just go out of fullscreen
481@@ -1658,8 +1658,6 @@
482 initPosition.y() + (initSize.height() - m_pView->height()) / 2);
483 }
484
485- WaveformWidgetFactory::instance()->start();
486-
487 #ifdef __APPLE__
488 // Original the following line fixes issue on OSX where menu bar went away
489 // after a skin change. It was original surrounded by #if __OSX__
490
491=== modified file 'mixxx/src/sounddeviceportaudio.cpp'
492--- mixxx/src/sounddeviceportaudio.cpp 2013-03-21 22:29:13 +0000
493+++ mixxx/src/sounddeviceportaudio.cpp 2013-05-01 22:08:27 +0000
494@@ -25,6 +25,7 @@
495 #include "sounddeviceportaudio.h"
496 #include "soundmanagerutil.h"
497 #include "controlobject.h"
498+#include "visualplayposition.h"
499 #include "util/timer.h"
500
501 SoundDevicePortAudio::SoundDevicePortAudio(ConfigObject<ConfigValue> *config, SoundManager *sm,
502@@ -326,6 +327,7 @@
503 m_bSetThreadPriority = true;
504 }
505
506+ VisualPlayPosition::setTimeInfo(timeInfo);
507 if (!m_undeflowUpdateCount) {
508 if (statusFlags & (paOutputUnderflow | paInputOverflow)) {
509 if (m_pMasterUnderflowCount) {
510
511=== added file 'mixxx/src/visualplayposition.cpp'
512--- mixxx/src/visualplayposition.cpp 1970-01-01 00:00:00 +0000
513+++ mixxx/src/visualplayposition.cpp 2013-05-01 22:08:27 +0000
514@@ -0,0 +1,109 @@
515+
516+#include <qdebug.h>
517+
518+#include "visualplayposition.h"
519+#include "controlobjectthreadmain.h"
520+#include "controlobject.h"
521+#include "waveform/waveformwidgetfactory.h"
522+#include "mathstuff.h"
523+#include "waveform/vsyncthread.h"
524+
525+
526+//static
527+QMap<QString, VisualPlayPosition*> VisualPlayPosition::m_listVisualPlayPosition;
528+const PaStreamCallbackTimeInfo* VisualPlayPosition::m_timeInfo;
529+PerformanceTimer VisualPlayPosition::m_timeInfoTime;
530+
531+VisualPlayPosition::VisualPlayPosition() :
532+ m_valid(false) {
533+
534+ m_audioBufferSize = new ControlObjectThreadMain(
535+ ControlObject::getControl(ConfigKey("[Master]","audio_buffer_size")));
536+}
537+
538+VisualPlayPosition::~VisualPlayPosition() {
539+
540+}
541+
542+// This function must be called only form the engine thread (PA callback)
543+void VisualPlayPosition::set(double playPos, double rate,
544+ double positionStep, double pSlipPosition) {
545+ VisualPlayPositionData data;
546+
547+ data.m_referenceTime = m_timeInfoTime;
548+ // Time from reference time to Buffer at DAC in µs
549+ data.m_timeDac = (m_timeInfo->outputBufferDacTime - m_timeInfo->currentTime) * 1000000;
550+ data.m_playPos = playPos;
551+ data.m_rate = rate;
552+ data.m_positionStep = positionStep;
553+ data.m_pSlipPosition = pSlipPosition;
554+
555+ // Atomic write
556+ m_data.setValue(data);
557+ m_valid = true;
558+}
559+
560+double VisualPlayPosition::getAt(VSyncThread* vsyncThread) {
561+ //static double testPos = 0;
562+ //testPos += 0.000017759; //0.000016608; // 1.46257e-05;
563+ //return testPos;
564+
565+ if (m_valid) {
566+ VisualPlayPositionData data = m_data.getValue();
567+ int usRefToVSync = vsyncThread->usFromTimerToNextSync(&data.m_referenceTime);
568+ int offset = usRefToVSync - data.m_timeDac;
569+ double playPos = data.m_playPos; // load playPos for the first sample in Buffer
570+ playPos += data.m_positionStep * offset * data.m_rate / m_audioBufferSize->get() / 1000;
571+ //qDebug() << "delta Pos" << playPos - m_playPosOld << offset;
572+ m_playPosOld = playPos;
573+ return playPos;
574+ }
575+ return -1;
576+}
577+
578+void VisualPlayPosition::getPlaySlipAt(int usFromNow, double* playPosition, double* slipPosition) {
579+ //static double testPos = 0;
580+ //testPos += 0.000017759; //0.000016608; // 1.46257e-05;
581+ //return testPos;
582+
583+ if (m_valid) {
584+ VisualPlayPositionData data = m_data.getValue();
585+ int usElapsed = data.m_referenceTime.elapsed() / 1000;
586+ int dacFromNow = usElapsed - data.m_timeDac;
587+ int offset = dacFromNow - usFromNow;
588+ double playPos = data.m_playPos; // load playPos for the first sample in Buffer
589+ playPos += data.m_positionStep * offset * data.m_rate / m_audioBufferSize->get() / 1000;
590+ *playPosition = playPos;
591+ *slipPosition = data.m_pSlipPosition;
592+ }
593+}
594+
595+double VisualPlayPosition::getEnginePlayPos() {
596+ if (m_valid) {
597+ VisualPlayPositionData data = m_data.getValue();
598+ return data.m_playPos;
599+ } else {
600+ return -1;
601+ }
602+}
603+
604+//static
605+VisualPlayPosition* VisualPlayPosition::getVisualPlayPosition(QString group) {
606+ VisualPlayPosition* vpp = m_listVisualPlayPosition[group];
607+ if (!vpp) {
608+ vpp = new VisualPlayPosition();
609+ m_listVisualPlayPosition[group] = vpp;
610+ }
611+ return vpp;
612+}
613+
614+//static
615+void VisualPlayPosition::setTimeInfo(const PaStreamCallbackTimeInfo *timeInfo) {
616+ m_timeInfo = timeInfo;
617+ m_timeInfoTime.start();
618+ //qDebug() << "TimeInfo" << (timeInfo->currentTime - floor(timeInfo->currentTime)) << (timeInfo->outputBufferDacTime - floor(timeInfo->outputBufferDacTime));
619+ //m_timeInfo.currentTime = timeInfo->currentTime;
620+ //m_timeInfo.inputBufferAdcTime = timeInfo->inputBufferAdcTime;
621+ //m_timeInfo.outputBufferDacTime = timeInfo->outputBufferDacTime;
622+}
623+
624
625=== added file 'mixxx/src/visualplayposition.h'
626--- mixxx/src/visualplayposition.h 1970-01-01 00:00:00 +0000
627+++ mixxx/src/visualplayposition.h 2013-05-01 22:08:27 +0000
628@@ -0,0 +1,57 @@
629+#ifndef VISUALPLAYPOSITION_H
630+#define VISUALPLAYPOSITION_H
631+
632+#include <portaudio.h>
633+#include "util/performancetimer.h"
634+#include "controlobjectbase.h"
635+
636+#include <QMutex>
637+#include <QTime>
638+#include <QMap>
639+#include <QAtomicPointer>
640+
641+class ControlObjectThreadMain;
642+class VSyncThread;
643+
644+class VisualPlayPositionData {
645+ public:
646+ PerformanceTimer m_referenceTime;
647+ int m_timeDac;
648+ double m_playPos;
649+ double m_rate;
650+ double m_positionStep;
651+ double m_pSlipPosition;
652+};
653+
654+
655+class VisualPlayPosition
656+{
657+ public:
658+ VisualPlayPosition();
659+ ~VisualPlayPosition();
660+
661+ void set(double playPos, double rate, double positionStep, double pSlipPosition);
662+ double getAt(VSyncThread* vsyncThread);
663+ void getPlaySlipAt(int usFromNow, double* playPosition, double* slipPosition);
664+ double getEnginePlayPos();
665+ static VisualPlayPosition* getVisualPlayPosition(QString group);
666+ static void setTimeInfo(const PaStreamCallbackTimeInfo *timeInfo);
667+ void setInvalid() { m_valid = false; };
668+
669+
670+ private:
671+ ControlObjectBase<VisualPlayPositionData> m_data;
672+ double m_playPosOld;
673+ int m_deltatime;
674+ ControlObjectThreadMain* m_audioBufferSize;
675+ PaTime m_outputBufferDacTime;
676+ bool m_valid;
677+
678+ static QMap<QString, VisualPlayPosition*> m_listVisualPlayPosition;
679+ static const PaStreamCallbackTimeInfo* m_timeInfo;
680+ static PerformanceTimer m_timeInfoTime;
681+
682+};
683+
684+#endif // VISUALPLAYPOSITION_H
685+
686
687=== added file 'mixxx/src/waveform/renderers/glvsynctestrenderer.cpp'
688--- mixxx/src/waveform/renderers/glvsynctestrenderer.cpp 1970-01-01 00:00:00 +0000
689+++ mixxx/src/waveform/renderers/glvsynctestrenderer.cpp 2013-05-01 22:08:27 +0000
690@@ -0,0 +1,133 @@
691+#include "glvsynctestrenderer.h"
692+
693+#include "waveformwidgetrenderer.h"
694+#include "waveform/waveform.h"
695+
696+#include "waveform/waveformwidgetfactory.h"
697+
698+#include "util/performancetimer.h"
699+
700+#include <qgl.h>
701+
702+GLVSyncTestRenderer::GLVSyncTestRenderer(
703+ WaveformWidgetRenderer* waveformWidgetRenderer)
704+ : WaveformRendererSignalBase(waveformWidgetRenderer),
705+ m_drawcount(0) {
706+}
707+
708+GLVSyncTestRenderer::~GLVSyncTestRenderer() {
709+}
710+
711+void GLVSyncTestRenderer::onSetup(const QDomNode &node) {
712+ Q_UNUSED(node);
713+}
714+
715+inline void setPoint(QPointF& point, qreal x, qreal y) {
716+ point.setX(x);
717+ point.setY(y);
718+}
719+
720+void GLVSyncTestRenderer::draw(QPainter* painter, QPaintEvent* /*event*/) {
721+
722+ PerformanceTimer timer;
723+ //int t5, t6, t7, t8, t9, t10, t11, t12, t13;
724+
725+
726+ timer.start();
727+
728+ TrackPointer pTrack = m_waveformRenderer->getTrackInfo();
729+ if (!pTrack) {
730+ return;
731+ }
732+
733+ const Waveform* waveform = pTrack->getWaveform();
734+ if (waveform == NULL) {
735+ return;
736+ }
737+
738+ const int dataSize = waveform->getDataSize();
739+ if (dataSize <= 1) {
740+ return;
741+ }
742+
743+ const WaveformData* data = waveform->data();
744+ if (data == NULL) {
745+ return;
746+ }
747+
748+ double firstVisualIndex = m_waveformRenderer->getFirstDisplayedPosition() * dataSize;
749+ double lastVisualIndex = m_waveformRenderer->getLastDisplayedPosition() * dataSize;
750+
751+ const int firstIndex = int(firstVisualIndex + 0.5);
752+ firstVisualIndex = firstIndex - firstIndex % 2;
753+
754+ const int lastIndex = int(lastVisualIndex + 0.5);
755+ lastVisualIndex = lastIndex + lastIndex % 2;
756+
757+ //t5 = timer.restart(); // 910
758+
759+ // Reset device for native painting
760+ painter->beginNativePainting();
761+
762+ //t6 = timer.restart(); // 29,150
763+
764+ glEnable(GL_BLEND);
765+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
766+
767+ const QColor& color = m_pColors->getSignalColor();
768+
769+ //t7 = timer.restart(); // 5,770
770+
771+ WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();
772+ const double visualGain = factory->getVisualGain(::WaveformWidgetFactory::All);
773+
774+ float maxAll[2];
775+
776+ glMatrixMode(GL_PROJECTION);
777+ glPushMatrix();
778+ glLoadIdentity();
779+
780+ //t8 = timer.restart(); // 2,611
781+
782+ if (m_alignment == Qt::AlignCenter) {
783+ glOrtho(firstVisualIndex, lastVisualIndex, -255.0, 255.0, -10.0, 10.0);
784+ } else if (m_alignment == Qt::AlignBottom) {
785+ glOrtho(firstVisualIndex, lastVisualIndex, 0.0, 255.0, -10.0, 10.0);
786+ } else {
787+ glOrtho(firstVisualIndex, lastVisualIndex, 255.0, 0.0, -10.0, 10.0);
788+ }
789+
790+ //t9 = timer.restart(); // 1,320
791+
792+ glMatrixMode(GL_MODELVIEW);
793+ glPushMatrix();
794+ glLoadIdentity();
795+
796+ //t10 = timer.restart(); // 915
797+
798+ if (++m_drawcount & 1) {
799+ glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
800+ glColor3f(1.0f, 1.0f, 1.0f);
801+ } else {
802+ glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
803+ glColor3f(1.0f, 0.0f, 0.0f);
804+ }
805+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
806+ glRectf(0, 0, 1, 1);
807+
808+ //t11 = timer.restart(); // 217,985
809+
810+ glEnd();
811+ glPopMatrix();
812+ glMatrixMode(GL_PROJECTION);
813+ glPopMatrix();
814+
815+ //t12 = timer.restart(); // 22,426
816+ painter->endNativePainting();
817+
818+ //t13 = timer.restart(); // 1,430
819+
820+ //qDebug() << t5 << t6 << t7 << t8 << t9 << t10 << t11 << t12 << t13;
821+
822+ //qDebug() << timer.restart(); // 129,498
823+}
824
825=== added file 'mixxx/src/waveform/renderers/glvsynctestrenderer.h'
826--- mixxx/src/waveform/renderers/glvsynctestrenderer.h 1970-01-01 00:00:00 +0000
827+++ mixxx/src/waveform/renderers/glvsynctestrenderer.h 2013-05-01 22:08:27 +0000
828@@ -0,0 +1,19 @@
829+#ifndef GLVSYNCTESTRENDERER_H
830+#define GLVSYNCTESTRENDERER_H
831+
832+#include "waveformrenderersignalbase.h"
833+
834+class ControlObject;
835+
836+class GLVSyncTestRenderer : public WaveformRendererSignalBase {
837+ public:
838+ explicit GLVSyncTestRenderer( WaveformWidgetRenderer* waveformWidgetRenderer);
839+ virtual ~GLVSyncTestRenderer();
840+
841+ virtual void onSetup(const QDomNode &node);
842+ virtual void draw(QPainter* painter, QPaintEvent* event);
843+ private:
844+ int m_drawcount;
845+};
846+
847+#endif // GLVSYNCTESTRENDERER_H
848
849=== modified file 'mixxx/src/waveform/renderers/waveformrenderbeat.cpp'
850--- mixxx/src/waveform/renderers/waveformrenderbeat.cpp 2013-04-12 15:06:58 +0000
851+++ mixxx/src/waveform/renderers/waveformrenderbeat.cpp 2013-05-01 22:08:27 +0000
852@@ -74,7 +74,7 @@
853
854 while (it->hasNext()) {
855 int beatPosition = it->next();
856- m_waveformRenderer->regulateVisualSample(beatPosition);
857+ // m_waveformRenderer->regulateVisualSample(beatPosition);
858 double xBeatPoint = m_waveformRenderer->transformSampleIndexInRendererWorld(beatPosition);
859
860 painter->setPen(beatPen);
861
862=== modified file 'mixxx/src/waveform/renderers/waveformrendererendoftrack.cpp'
863--- mixxx/src/waveform/renderers/waveformrendererendoftrack.cpp 2013-01-28 13:06:12 +0000
864+++ mixxx/src/waveform/renderers/waveformrendererendoftrack.cpp 2013-05-01 22:08:27 +0000
865@@ -13,6 +13,8 @@
866 #include "widget/wskincolor.h"
867 #include "widget/wwidget.h"
868
869+#include "util/timer.h"
870+
871 WaveformRendererEndOfTrack::WaveformRendererEndOfTrack(
872 WaveformWidgetRenderer* waveformWidgetRenderer)
873 : WaveformRendererAbstract(waveformWidgetRenderer),
874@@ -61,14 +63,20 @@
875 }
876
877 void WaveformRendererEndOfTrack::onResize() {
878- m_rect = QRect( 0, 0, m_waveformRenderer->getWidth(), m_waveformRenderer->getHeight());
879 m_backRects.resize(4);
880 for (int i = 0; i < 4; i++) {
881 m_backRects[i].setTop(0);
882 m_backRects[i].setBottom(m_waveformRenderer->getHeight());
883- m_backRects[i].setLeft(m_waveformRenderer->getWidth()/2+i*m_waveformRenderer->getWidth()/8);
884+ m_backRects[i].setLeft(m_waveformRenderer->getWidth()/2 +
885+ i*m_waveformRenderer->getWidth()/8);
886 m_backRects[i].setRight(m_waveformRenderer->getWidth());
887 }
888+ /*
889+ m_gradient.setStart(m_waveformRenderer->getWidth()/2, 0);
890+ m_gradient.setFinalStop(m_waveformRenderer->getWidth(), 0);
891+ m_gradient.setColorAt(0, Qt::transparent);
892+ m_gradient.setColorAt(1, m_color);
893+ */
894 }
895
896 void WaveformRendererEndOfTrack::draw(QPainter* painter,
897@@ -121,6 +129,8 @@
898 //qDebug() << "EndOfTrack ON";
899 }
900
901+ ScopedTimer t("WaveformRendererEndOfTrack::draw");
902+
903 const int elapsed = m_timer.elapsed() % m_blinkingPeriodMillis;
904
905 const double blickIntensity = (double)(2 * abs(elapsed - m_blinkingPeriodMillis/2)) /
906@@ -139,5 +149,9 @@
907 painter->setPen(QPen(Qt::transparent));
908 painter->setBrush(m_color);
909 painter->drawRects(m_backRects);
910+ //painter->setOpacity(0.5 * criticalIntensity * blickIntensity);
911+ //painter->fillRect(m_waveformRenderer->getWidth()/2, 1,
912+ // m_waveformRenderer->getWidth() - 2, m_waveformRenderer->getHeight() - 2,
913+ // m_gradient);
914 painter->restore();
915 }
916
917=== modified file 'mixxx/src/waveform/renderers/waveformrendererendoftrack.h'
918--- mixxx/src/waveform/renderers/waveformrendererendoftrack.h 2012-12-14 01:26:04 +0000
919+++ mixxx/src/waveform/renderers/waveformrendererendoftrack.h 2013-05-01 22:08:27 +0000
920@@ -3,6 +3,7 @@
921
922 #include <QColor>
923 #include <QTime>
924+#include <QLinearGradient>
925
926 #include "util.h"
927 #include "waveformrendererabstract.h"
928@@ -35,9 +36,9 @@
929 int m_blinkingPeriodMillis;
930 double m_remainingTimeTriggerSeconds;
931
932- QRect m_rect;
933 QVector<QRect> m_backRects;
934 QPen m_pen;
935+ QLinearGradient m_gradient;
936
937 DISALLOW_COPY_AND_ASSIGN(WaveformRendererEndOfTrack);
938 };
939
940=== added file 'mixxx/src/waveform/renderers/waveformrendererhsv.cpp'
941--- mixxx/src/waveform/renderers/waveformrendererhsv.cpp 1970-01-01 00:00:00 +0000
942+++ mixxx/src/waveform/renderers/waveformrendererhsv.cpp 2013-05-01 22:08:27 +0000
943@@ -0,0 +1,177 @@
944+#include "waveformrendererhsv.h"
945+
946+#include "waveformwidgetrenderer.h"
947+#include "waveform/waveform.h"
948+#include "waveform/waveformwidgetfactory.h"
949+
950+#include "widget/wskincolor.h"
951+#include "trackinfoobject.h"
952+#include "widget/wwidget.h"
953+
954+#include "defs.h"
955+
956+#include "controlobjectthreadmain.h"
957+
958+WaveformRendererHSV::WaveformRendererHSV(
959+ WaveformWidgetRenderer* waveformWidgetRenderer)
960+ : WaveformRendererSignalBase( waveformWidgetRenderer) {
961+}
962+
963+WaveformRendererHSV::~WaveformRendererHSV() {
964+}
965+
966+void WaveformRendererHSV::onSetup(const QDomNode& node) {
967+ Q_UNUSED(node);
968+}
969+
970+void WaveformRendererHSV::draw(QPainter* painter,
971+ QPaintEvent* /*event*/) {
972+ const TrackPointer trackInfo = m_waveformRenderer->getTrackInfo();
973+ if (!trackInfo) {
974+ return;
975+ }
976+
977+ const Waveform* waveform = trackInfo->getWaveform();
978+ if (waveform == NULL) {
979+ return;
980+ }
981+
982+ const int dataSize = waveform->getDataSize();
983+ if (dataSize <= 1) {
984+ return;
985+ }
986+
987+ const WaveformData* data = waveform->data();
988+ if (data == NULL) {
989+ return;
990+ }
991+
992+ painter->save();
993+ painter->setRenderHints(QPainter::Antialiasing, false);
994+ painter->setRenderHints(QPainter::HighQualityAntialiasing, false);
995+ painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
996+ painter->setWorldMatrixEnabled(false);
997+ painter->resetTransform();
998+
999+ const double firstVisualIndex = m_waveformRenderer->getFirstDisplayedPosition() * dataSize;
1000+ const double lastVisualIndex = m_waveformRenderer->getLastDisplayedPosition() * dataSize;
1001+
1002+ const double offset = firstVisualIndex;
1003+
1004+ // Represents the # of waveform data points per horizontal pixel.
1005+ const double gain = (lastVisualIndex - firstVisualIndex) /
1006+ (double)m_waveformRenderer->getWidth();
1007+
1008+ float allGain(1.0);
1009+ allGain = m_waveformRenderer->getGain();
1010+
1011+ WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();
1012+ allGain *= factory->getVisualGain(::WaveformWidgetFactory::All);
1013+
1014+ // Save HSV of waveform color
1015+ double h,s,v;
1016+
1017+ // Get base color of waveform in the HSV format (s and v isn't use)
1018+ m_pColors->getLowColor().getHsvF(&h,&s,&v);
1019+
1020+ QColor color;
1021+ float lo, hi, total;
1022+
1023+ const float halfHeight = (float)m_waveformRenderer->getHeight()/2.0;
1024+
1025+ const float heightFactor = allGain*halfHeight/255.0;
1026+
1027+ //draw reference line
1028+ painter->setPen(m_axesColor);
1029+ painter->drawLine(0,halfHeight,m_waveformRenderer->getWidth(),halfHeight);
1030+
1031+ for (int x = 0; x < m_waveformRenderer->getWidth(); ++x) {
1032+ // Width of the x position in visual indices.
1033+ const double xSampleWidth = gain * x;
1034+
1035+ // Effective visual index of x
1036+ const double xVisualSampleIndex = xSampleWidth + offset;
1037+
1038+ // Our current pixel (x) corresponds to a number of visual samples
1039+ // (visualSamplerPerPixel) in our waveform object. We take the max of
1040+ // all the data points on either side of xVisualSampleIndex within a
1041+ // window of 'maxSamplingRange' visual samples to measure the maximum
1042+ // data point contained by this pixel.
1043+ double maxSamplingRange = gain / 2.0;
1044+
1045+ // Since xVisualSampleIndex is in visual-samples (e.g. R,L,R,L) we want
1046+ // to check +/- maxSamplingRange frames, not samples. To do this, divide
1047+ // xVisualSampleIndex by 2. Since frames indices are integers, we round
1048+ // to the nearest integer by adding 0.5 before casting to int.
1049+ int visualFrameStart = int(xVisualSampleIndex / 2.0 - maxSamplingRange + 0.5);
1050+ int visualFrameStop = int(xVisualSampleIndex / 2.0 + maxSamplingRange + 0.5);
1051+ const int lastVisualFrame = dataSize / 2 - 1;
1052+
1053+ // We now know that some subset of [visualFrameStart, visualFrameStop]
1054+ // lies within the valid range of visual frames. Clamp
1055+ // visualFrameStart/Stop to within [0, lastVisualFrame].
1056+ visualFrameStart = math_max(math_min(lastVisualFrame, visualFrameStart), 0);
1057+ visualFrameStop = math_max(math_min(lastVisualFrame, visualFrameStop), 0);
1058+
1059+ int visualIndexStart = visualFrameStart * 2;
1060+ int visualIndexStop = visualFrameStop * 2;
1061+
1062+ int maxLow[2] = {0, 0};
1063+ int maxHigh[2] = {0, 0};
1064+ int maxMid[2] = {0, 0};
1065+ int maxAll[2] = {0, 0};
1066+
1067+ for (int i = visualIndexStart;
1068+ i >= 0 && i + 1 < dataSize && i + 1 <= visualIndexStop; i += 2) {
1069+ const WaveformData& waveformData = *(data + i);
1070+ const WaveformData& waveformDataNext = *(data + i + 1);
1071+ maxLow[0] = math_max(maxLow[0], (int)waveformData.filtered.low);
1072+ maxLow[1] = math_max(maxLow[1], (int)waveformDataNext.filtered.low);
1073+ maxMid[0] = math_max(maxMid[0], (int)waveformData.filtered.mid);
1074+ maxMid[1] = math_max(maxMid[1], (int)waveformDataNext.filtered.mid);
1075+ maxHigh[0] = math_max(maxHigh[0], (int)waveformData.filtered.high);
1076+ maxHigh[1] = math_max(maxHigh[1], (int)waveformDataNext.filtered.high);
1077+ maxAll[0] = math_max( maxAll[0], (int)waveformData.filtered.all);
1078+ maxAll[1] = math_max( maxAll[1], (int)waveformDataNext.filtered.all);
1079+ }
1080+
1081+ if( maxAll[0] && maxAll[1] ) {
1082+ // Calculate sum, to normalize
1083+ // Also multiply on 1.2 to prevent very dark or light color
1084+ total = (maxLow[0] + maxLow[1] + maxMid[0] + maxMid[1] + maxHigh[0] + maxHigh[1]) * 1.2;
1085+
1086+ // prevent division by zero
1087+ if( total > 0 )
1088+ {
1089+ // Normalize low and high (mid not need, because it not change the color)
1090+ lo = (maxLow[0] + maxLow[1]) / total;
1091+ hi = (maxHigh[0] + maxHigh[1]) / total;
1092+ }
1093+ else
1094+ lo = hi = 0.0;
1095+
1096+ // Set color
1097+ color.setHsvF(h, 1.0-hi, 1.0-lo);
1098+
1099+ painter->setPen(color);
1100+ switch (m_alignment) {
1101+ case Qt::AlignBottom :
1102+ painter->drawLine(
1103+ x, m_waveformRenderer->getHeight(),
1104+ x, m_waveformRenderer->getHeight() - (int)(heightFactor*(float)math_max(maxAll[0],maxAll[1])));
1105+ break;
1106+ case Qt::AlignTop :
1107+ painter->drawLine(
1108+ x, 0,
1109+ x, (int)(heightFactor*(float)math_max(maxAll[0],maxAll[1])));
1110+ break;
1111+ default :
1112+ painter->drawLine(
1113+ x, (int)(halfHeight-heightFactor*(float)maxAll[0]),
1114+ x, (int)(halfHeight+heightFactor*(float)maxAll[1]));
1115+ }
1116+ }
1117+ }
1118+
1119+ painter->restore();
1120+}
1121
1122=== removed file 'mixxx/src/waveform/renderers/waveformrendererhsv.cpp'
1123--- mixxx/src/waveform/renderers/waveformrendererhsv.cpp 2013-01-16 21:03:36 +0000
1124+++ mixxx/src/waveform/renderers/waveformrendererhsv.cpp 1970-01-01 00:00:00 +0000
1125@@ -1,177 +0,0 @@
1126-#include "waveformrendererhsv.h"
1127-
1128-#include "waveformwidgetrenderer.h"
1129-#include "waveform/waveform.h"
1130-#include "waveform/waveformwidgetfactory.h"
1131-
1132-#include "widget/wskincolor.h"
1133-#include "trackinfoobject.h"
1134-#include "widget/wwidget.h"
1135-
1136-#include "defs.h"
1137-
1138-#include "controlobjectthreadmain.h"
1139-
1140-WaveformRendererHSV::WaveformRendererHSV(
1141- WaveformWidgetRenderer* waveformWidgetRenderer)
1142- : WaveformRendererSignalBase( waveformWidgetRenderer) {
1143-}
1144-
1145-WaveformRendererHSV::~WaveformRendererHSV() {
1146-}
1147-
1148-void WaveformRendererHSV::onSetup(const QDomNode& node) {
1149- Q_UNUSED(node);
1150-}
1151-
1152-void WaveformRendererHSV::draw(QPainter* painter,
1153- QPaintEvent* /*event*/) {
1154- const TrackPointer trackInfo = m_waveformRenderer->getTrackInfo();
1155- if (!trackInfo) {
1156- return;
1157- }
1158-
1159- const Waveform* waveform = trackInfo->getWaveform();
1160- if (waveform == NULL) {
1161- return;
1162- }
1163-
1164- const int dataSize = waveform->getDataSize();
1165- if (dataSize <= 1) {
1166- return;
1167- }
1168-
1169- const WaveformData* data = waveform->data();
1170- if (data == NULL) {
1171- return;
1172- }
1173-
1174- painter->save();
1175- painter->setRenderHints(QPainter::Antialiasing, false);
1176- painter->setRenderHints(QPainter::HighQualityAntialiasing, false);
1177- painter->setRenderHints(QPainter::SmoothPixmapTransform, false);
1178- painter->setWorldMatrixEnabled(false);
1179- painter->resetTransform();
1180-
1181- const double firstVisualIndex = m_waveformRenderer->getFirstDisplayedPosition() * dataSize;
1182- const double lastVisualIndex = m_waveformRenderer->getLastDisplayedPosition() * dataSize;
1183-
1184- const double offset = firstVisualIndex;
1185-
1186- // Represents the # of waveform data points per horizontal pixel.
1187- const double gain = (lastVisualIndex - firstVisualIndex) /
1188- (double)m_waveformRenderer->getWidth();
1189-
1190- float allGain(1.0);
1191- allGain = m_waveformRenderer->getGain();
1192-
1193- WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();
1194- allGain *= factory->getVisualGain(::WaveformWidgetFactory::All);
1195-
1196- // Save HSV of waveform color
1197- double h,s,v;
1198-
1199- // Get base color of waveform in the HSV format (s and v isn't use)
1200- m_pColors->getLowColor().getHsvF(&h,&s,&v);
1201-
1202- QColor color;
1203- float lo, hi, total;
1204-
1205- const float halfHeight = (float)m_waveformRenderer->getHeight()/2.0;
1206-
1207- const float heightFactor = allGain*halfHeight/255.0;
1208-
1209- //draw reference line
1210- painter->setPen(m_axesColor);
1211- painter->drawLine(0,halfHeight,m_waveformRenderer->getWidth(),halfHeight);
1212-
1213- for (int x = 0; x < m_waveformRenderer->getWidth(); ++x) {
1214- // Width of the x position in visual indices.
1215- const double xSampleWidth = gain * x;
1216-
1217- // Effective visual index of x
1218- const double xVisualSampleIndex = xSampleWidth + offset;
1219-
1220- // Our current pixel (x) corresponds to a number of visual samples
1221- // (visualSamplerPerPixel) in our waveform object. We take the max of
1222- // all the data points on either side of xVisualSampleIndex within a
1223- // window of 'maxSamplingRange' visual samples to measure the maximum
1224- // data point contained by this pixel.
1225- double maxSamplingRange = gain / 2.0;
1226-
1227- // Since xVisualSampleIndex is in visual-samples (e.g. R,L,R,L) we want
1228- // to check +/- maxSamplingRange frames, not samples. To do this, divide
1229- // xVisualSampleIndex by 2. Since frames indices are integers, we round
1230- // to the nearest integer by adding 0.5 before casting to int.
1231- int visualFrameStart = int(xVisualSampleIndex / 2.0 - maxSamplingRange + 0.5);
1232- int visualFrameStop = int(xVisualSampleIndex / 2.0 + maxSamplingRange + 0.5);
1233- const int lastVisualFrame = dataSize / 2 - 1;
1234-
1235- // We now know that some subset of [visualFrameStart, visualFrameStop]
1236- // lies within the valid range of visual frames. Clamp
1237- // visualFrameStart/Stop to within [0, lastVisualFrame].
1238- visualFrameStart = math_max(math_min(lastVisualFrame, visualFrameStart), 0);
1239- visualFrameStop = math_max(math_min(lastVisualFrame, visualFrameStop), 0);
1240-
1241- int visualIndexStart = visualFrameStart * 2;
1242- int visualIndexStop = visualFrameStop * 2;
1243-
1244- int maxLow[2] = {0, 0};
1245- int maxHigh[2] = {0, 0};
1246- int maxMid[2] = {0, 0};
1247- int maxAll[2] = {0, 0};
1248-
1249- for (int i = visualIndexStart;
1250- i >= 0 && i + 1 < dataSize && i + 1 <= visualIndexStop; i += 2) {
1251- const WaveformData& waveformData = *(data + i);
1252- const WaveformData& waveformDataNext = *(data + i + 1);
1253- maxLow[0] = math_max(maxLow[0], (int)waveformData.filtered.low);
1254- maxLow[1] = math_max(maxLow[1], (int)waveformDataNext.filtered.low);
1255- maxMid[0] = math_max(maxMid[0], (int)waveformData.filtered.mid);
1256- maxMid[1] = math_max(maxMid[1], (int)waveformDataNext.filtered.mid);
1257- maxHigh[0] = math_max(maxHigh[0], (int)waveformData.filtered.high);
1258- maxHigh[1] = math_max(maxHigh[1], (int)waveformDataNext.filtered.high);
1259- maxAll[0] = math_max( maxAll[0], (int)waveformData.filtered.all);
1260- maxAll[1] = math_max( maxAll[1], (int)waveformDataNext.filtered.all);
1261- }
1262-
1263- if( maxAll[0] && maxAll[1] ) {
1264- // Calculate sum, to normalize
1265- // Also multiply on 1.2 to prevent very dark or light color
1266- total = (maxLow[0] + maxLow[1] + maxMid[0] + maxMid[1] + maxHigh[0] + maxHigh[1]) * 1.2;
1267-
1268- // prevent division by zero
1269- if( total > 0 )
1270- {
1271- // Normalize low and high (mid not need, because it not change the color)
1272- lo = (maxLow[0] + maxLow[1]) / total;
1273- hi = (maxHigh[0] + maxHigh[1]) / total;
1274- }
1275- else
1276- lo = hi = 0.0;
1277-
1278- // Set color
1279- color.setHsvF(h, 1.0-hi, 1.0-lo);
1280-
1281- painter->setPen(color);
1282- switch (m_alignment) {
1283- case Qt::AlignBottom :
1284- painter->drawLine(
1285- x, m_waveformRenderer->getHeight(),
1286- x, m_waveformRenderer->getHeight() - (int)(heightFactor*(float)math_max(maxAll[0],maxAll[1])));
1287- break;
1288- case Qt::AlignTop :
1289- painter->drawLine(
1290- x, 0,
1291- x, (int)(heightFactor*(float)math_max(maxAll[0],maxAll[1])));
1292- break;
1293- default :
1294- painter->drawLine(
1295- x, (int)(halfHeight-heightFactor*(float)maxAll[0]),
1296- x, (int)(halfHeight+heightFactor*(float)maxAll[1]));
1297- }
1298- }
1299- }
1300-
1301- painter->restore();
1302-}
1303
1304=== added file 'mixxx/src/waveform/renderers/waveformrendererhsv.h'
1305--- mixxx/src/waveform/renderers/waveformrendererhsv.h 1970-01-01 00:00:00 +0000
1306+++ mixxx/src/waveform/renderers/waveformrendererhsv.h 2013-05-01 22:08:27 +0000
1307@@ -0,0 +1,21 @@
1308+#ifndef WAVEFORMRENDERERHSV_H
1309+#define WAVEFORMRENDERERHSV_H
1310+
1311+#include "waveformrenderersignalbase.h"
1312+#include "util.h"
1313+
1314+class WaveformRendererHSV : public WaveformRendererSignalBase {
1315+ public:
1316+ explicit WaveformRendererHSV(
1317+ WaveformWidgetRenderer* waveformWidget);
1318+ virtual ~WaveformRendererHSV();
1319+
1320+ virtual void onSetup(const QDomNode& node);
1321+
1322+ virtual void draw(QPainter* painter, QPaintEvent* event);
1323+
1324+ private:
1325+ DISALLOW_COPY_AND_ASSIGN(WaveformRendererHSV);
1326+};
1327+
1328+#endif // WAVEFORMRENDERERFILTEREDSIGNAL_H
1329
1330=== removed file 'mixxx/src/waveform/renderers/waveformrendererhsv.h'
1331--- mixxx/src/waveform/renderers/waveformrendererhsv.h 2012-12-14 01:26:04 +0000
1332+++ mixxx/src/waveform/renderers/waveformrendererhsv.h 1970-01-01 00:00:00 +0000
1333@@ -1,21 +0,0 @@
1334-#ifndef WAVEFORMRENDERERHSV_H
1335-#define WAVEFORMRENDERERHSV_H
1336-
1337-#include "waveformrenderersignalbase.h"
1338-#include "util.h"
1339-
1340-class WaveformRendererHSV : public WaveformRendererSignalBase {
1341- public:
1342- explicit WaveformRendererHSV(
1343- WaveformWidgetRenderer* waveformWidget);
1344- virtual ~WaveformRendererHSV();
1345-
1346- virtual void onSetup(const QDomNode& node);
1347-
1348- virtual void draw(QPainter* painter, QPaintEvent* event);
1349-
1350- private:
1351- DISALLOW_COPY_AND_ASSIGN(WaveformRendererHSV);
1352-};
1353-
1354-#endif // WAVEFORMRENDERERFILTEREDSIGNAL_H
1355
1356=== modified file 'mixxx/src/waveform/renderers/waveformrendererpreroll.cpp'
1357--- mixxx/src/waveform/renderers/waveformrendererpreroll.cpp 2012-11-20 21:24:37 +0000
1358+++ mixxx/src/waveform/renderers/waveformrendererpreroll.cpp 2013-05-01 22:08:27 +0000
1359@@ -29,14 +29,13 @@
1360 if (!track) {
1361 return;
1362 }
1363- const Waveform* waveform = track->getWaveform();
1364 double samplesPerPixel = m_waveformRenderer->getVisualSamplePerPixel();
1365 double numberOfSamples = m_waveformRenderer->getWidth() * samplesPerPixel;
1366
1367 // TODO (vRince) not really accurate since waveform size une visual reasampling and
1368 // have two mores samples to hold the complete visual data
1369- int currentPosition = m_waveformRenderer->getPlayPos() * waveform->getDataSize();
1370- m_waveformRenderer->regulateVisualSample(currentPosition);
1371+ int currentPosition = m_waveformRenderer->getPlayPosVSample();
1372+ // m_waveformRenderer->regulateVisualSample(currentPosition);
1373
1374 // Some of the pre-roll is on screen. Draw little triangles to indicate
1375 // where the pre-roll is located.
1376@@ -47,6 +46,9 @@
1377 const float halfPolyHeight = m_waveformRenderer->getHeight()/5.0;
1378
1379 painter->save();
1380+ painter->setRenderHint(QPainter::Antialiasing);
1381+ //painter->setRenderHint(QPainter::HighQualityAntialiasing);
1382+ //painter->setBackgroundMode(Qt::TransparentMode);
1383 painter->setWorldMatrixEnabled(false);
1384 painter->setPen(QPen(QBrush(m_color), 1));
1385 QPolygonF polygon;
1386
1387=== modified file 'mixxx/src/waveform/renderers/waveformrendermark.cpp'
1388--- mixxx/src/waveform/renderers/waveformrendermark.cpp 2013-03-27 21:32:51 +0000
1389+++ mixxx/src/waveform/renderers/waveformrendermark.cpp 2013-05-01 22:08:27 +0000
1390@@ -48,8 +48,8 @@
1391 }
1392
1393 int samplePosition = mark.m_pointControl->get();
1394- if (samplePosition >= 0.0) {
1395- m_waveformRenderer->regulateVisualSample(samplePosition);
1396+ if (samplePosition > 0.0) {
1397+ //m_waveformRenderer->regulateVisualSample(samplePosition);
1398 double currentMarkPoint = m_waveformRenderer->transformSampleIndexInRendererWorld(samplePosition);
1399
1400 // NOTE: vRince I guess image width is odd to display the center on the exact line !
1401
1402=== modified file 'mixxx/src/waveform/renderers/waveformrendermarkrange.cpp'
1403--- mixxx/src/waveform/renderers/waveformrendermarkrange.cpp 2013-01-31 19:48:57 +0000
1404+++ mixxx/src/waveform/renderers/waveformrendermarkrange.cpp 2013-05-01 22:08:27 +0000
1405@@ -58,10 +58,10 @@
1406 int startSample = markRange.start();
1407 int endSample = markRange.end();
1408
1409- m_waveformRenderer->regulateVisualSample(startSample);
1410+ //m_waveformRenderer->regulateVisualSample(startSample);
1411 double startPosition = m_waveformRenderer->transformSampleIndexInRendererWorld(startSample);
1412
1413- m_waveformRenderer->regulateVisualSample(endSample);
1414+ //m_waveformRenderer->regulateVisualSample(endSample);
1415 double endPosition = m_waveformRenderer->transformSampleIndexInRendererWorld(endSample);
1416
1417 //range not in the current display
1418
1419=== modified file 'mixxx/src/waveform/renderers/waveformwidgetrenderer.cpp'
1420--- mixxx/src/waveform/renderers/waveformwidgetrenderer.cpp 2013-01-31 21:53:32 +0000
1421+++ mixxx/src/waveform/renderers/waveformwidgetrenderer.cpp 2013-05-01 22:08:27 +0000
1422@@ -6,56 +6,49 @@
1423 #include "controlobjectthreadmain.h"
1424 #include "controlobject.h"
1425 #include "defs.h"
1426+#include "visualplayposition.h"
1427 #include "mathstuff.h"
1428
1429+#include "util/performancetimer.h"
1430+
1431+#include <QPainter>
1432+
1433 const int WaveformWidgetRenderer::s_waveformMinZoom = 1;
1434 const int WaveformWidgetRenderer::s_waveformMaxZoom = 6;
1435
1436-WaveformWidgetRenderer::WaveformWidgetRenderer() {
1437- m_playPosControlObject = NULL;
1438- m_rateControlObject = NULL;
1439- m_rateRangeControlObject = NULL;
1440- m_rateDirControlObject = NULL;
1441- m_gainControlObject = NULL;
1442- m_trackSamplesControlObject = NULL;
1443-
1444-#ifdef WAVEFORMWIDGETRENDERER_DEBUG
1445- m_timer = NULL;
1446-#endif
1447-}
1448-
1449-WaveformWidgetRenderer::WaveformWidgetRenderer( const char* group) :
1450- m_group(group),
1451- m_trackInfoObject(0),
1452- m_height(-1),
1453- m_width(-1) {
1454+WaveformWidgetRenderer::WaveformWidgetRenderer( const char* group)
1455+ : m_group(group),
1456+ m_trackInfoObject(0),
1457+ m_height(-1),
1458+ m_width(-1),
1459+
1460+ m_firstDisplayedPosition(0.0),
1461+ m_lastDisplayedPosition(0.0),
1462+ m_rendererTransformationOffset(0.0),
1463+ m_rendererTransformationGain(0.0),
1464+
1465+ m_zoomFactor(1.0),
1466+ m_rateAdjust(0.0),
1467+ m_visualSamplePerPixel(1.0),
1468+ m_audioSamplePerPixel(1.0),
1469+
1470+ // Really create some to manage those;
1471+ m_visualPlayPosition(NULL),
1472+ m_playPos(-1),
1473+ m_playPosVSample(0),
1474+ m_rateControlObject(NULL),
1475+ m_rate(0.0),
1476+ m_rateRangeControlObject(NULL),
1477+ m_rateRange(0.0),
1478+ m_rateDirControlObject(NULL),
1479+ m_rateDir(0.0),
1480+ m_gainControlObject(NULL),
1481+ m_gain(1.0),
1482+ m_trackSamplesControlObject(NULL),
1483+ m_trackSamples(0.0) {
1484+
1485 //qDebug() << "WaveformWidgetRenderer";
1486
1487- m_firstDisplayedPosition = 0.0;
1488- m_lastDisplayedPosition = 0.0;
1489- m_rendererTransformationOffset = 0.0;
1490- m_rendererTransformationGain = 0.0;
1491-
1492- m_zoomFactor = 1.0;
1493- m_rateAdjust = 0.0;
1494- m_visualSamplePerPixel = 1.0;
1495- m_audioSamplePerPixel = 1.0;
1496-
1497- // Really create some to manage those
1498- m_playPosControlObject = NULL;
1499- m_playPos = 0.0;
1500- m_rateControlObject = NULL;
1501- m_rate = 0.0;
1502- m_rateRangeControlObject = NULL;
1503- m_rateRange = 0.0;
1504- m_rateDirControlObject = NULL;
1505- m_rateDir = 0.0;
1506- m_gainControlObject = NULL;
1507- m_gain = 1.0;
1508- m_trackSamplesControlObject = NULL;
1509- m_trackSamples = -1.0;
1510-
1511-
1512 #ifdef WAVEFORMWIDGETRENDERER_DEBUG
1513 m_timer = new QTime();
1514 currentFrame = 0;
1515@@ -74,7 +67,6 @@
1516 for( int i = 0; i < m_rendererStack.size(); ++i)
1517 delete m_rendererStack[i];
1518
1519- delete m_playPosControlObject;
1520 delete m_rateControlObject;
1521 delete m_rateRangeControlObject;
1522 delete m_rateDirControlObject;
1523@@ -89,9 +81,8 @@
1524 bool WaveformWidgetRenderer::init() {
1525
1526 //qDebug() << "WaveformWidgetRenderer::init";
1527+ m_visualPlayPosition = VisualPlayPosition::getVisualPlayPosition(m_group);
1528
1529- m_playPosControlObject = new ControlObjectThreadMain(
1530- ControlObject::getControl( ConfigKey(m_group, "visual_playposition")));
1531 m_rateControlObject = new ControlObjectThreadMain(
1532 ControlObject::getControl( ConfigKey(m_group, "rate")));
1533 m_rateRangeControlObject = new ControlObjectThreadMain(
1534@@ -111,7 +102,7 @@
1535 return true;
1536 }
1537
1538-void WaveformWidgetRenderer::onPreRender() {
1539+void WaveformWidgetRenderer::onPreRender(VSyncThread* vsyncThread) {
1540 // For a valid track to render we need
1541 m_trackSamples = m_trackSamplesControlObject->get();
1542 if (m_trackSamples <= 0.0) {
1543@@ -141,7 +132,7 @@
1544 m_audioSamplePerPixel = 0.0;
1545 }
1546
1547- m_playPos = m_playPosControlObject->get();
1548+ m_playPos = m_visualPlayPosition->getAt(vsyncThread);
1549 // m_playPos = -1 happens, when a new track is in buffer but m_visualPlayPosition was not updated
1550
1551 if (m_audioSamplePerPixel && m_playPos != -1) {
1552@@ -153,7 +144,9 @@
1553 double displayedLengthHalf = static_cast<double>(m_width) / trackPixel / 2.0;
1554 // Avoid pixel jitter in play position by rounding to the nearest track
1555 // pixel.
1556- m_playPos = round(m_playPosControlObject->get() * trackPixel) / trackPixel;
1557+ m_playPos = round(m_playPos * trackPixel)/(double)trackPixel; // Avoid pixel jitter in play position
1558+ m_playPosVSample = m_playPos * m_trackInfoObject->getWaveform()->getDataSize();
1559+
1560 m_firstDisplayedPosition = m_playPos - displayedLengthHalf;
1561 m_lastDisplayedPosition = m_playPos + displayedLengthHalf;
1562 m_rendererTransformationOffset = - m_firstDisplayedPosition;
1563@@ -181,6 +174,9 @@
1564 m_lastSystemFrameTime = m_timer->restart();
1565 #endif
1566
1567+// PerformanceTimer timer;
1568+// timer.start();
1569+
1570 //not ready to display need to wait until track initialization is done
1571 //draw only first is stack (background)
1572 int stackSize = m_rendererStack.size();
1573@@ -191,7 +187,9 @@
1574 return;
1575 } else {
1576 for (int i = 0; i < stackSize; i++) {
1577+ // qDebug() << i << " a " << timer.restart();
1578 m_rendererStack.at(i)->draw(painter, event);
1579+ // qDebug() << i << " e " << timer.restart();
1580 }
1581
1582 painter->setPen(m_colors.getPlayPosColor());
1583@@ -215,7 +213,8 @@
1584 QString::number(m_lastFrameTime).rightJustified(2,'0') + "(" +
1585 QString::number(frameMax).rightJustified(2,'0') + ")" +
1586 QString::number(m_lastSystemFrameTime) + "(" +
1587- QString::number(systemMax) + ")");
1588+ QString::number(systemMax) + ")" +
1589+ QString::number(realtimeError));
1590
1591 painter->drawText(1,m_height-1,
1592 QString::number(m_playPos) + " [" +
1593@@ -234,6 +233,7 @@
1594 m_lastFramesTime[currentFrame] = m_lastFrameTime;
1595 #endif
1596
1597+ // qDebug() << "draw() ende" << timer.restart();
1598 }
1599
1600 void WaveformWidgetRenderer::resize( int width, int height) {
1601
1602=== modified file 'mixxx/src/waveform/renderers/waveformwidgetrenderer.h'
1603--- mixxx/src/waveform/renderers/waveformwidgetrenderer.h 2013-01-31 21:53:32 +0000
1604+++ mixxx/src/waveform/renderers/waveformwidgetrenderer.h 2013-05-01 22:08:27 +0000
1605@@ -15,6 +15,8 @@
1606
1607 class TrackInfoObject;
1608 class ControlObjectThreadMain;
1609+class VisualPlayPosition;
1610+class VSyncThread;
1611
1612 class WaveformWidgetRenderer {
1613 public:
1614@@ -29,7 +31,7 @@
1615 virtual bool onInit() {return true;}
1616
1617 void setup(const QDomNode& node);
1618- void onPreRender();
1619+ void onPreRender(VSyncThread* vsyncThread);
1620 void draw(QPainter* painter, QPaintEvent* event);
1621
1622 const char* getGroup() const { return m_group;}
1623@@ -56,6 +58,7 @@
1624 double transformPositionInRendererWorld(double position) const;
1625
1626 double getPlayPos() const { return m_playPos;}
1627+ double getPlayPosVSample() const { return m_playPosVSample;}
1628 double getZoomFactor() const { return m_zoomFactor;}
1629 double getRateAdjust() const { return m_rateAdjust;}
1630 double getGain() const { return m_gain;}
1631@@ -78,7 +81,7 @@
1632 protected:
1633 const char* m_group;
1634 TrackPointer m_trackInfoObject;
1635- QVector<WaveformRendererAbstract*> m_rendererStack;
1636+ QList<WaveformRendererAbstract*> m_rendererStack;
1637 int m_height;
1638 int m_width;
1639 WaveformSignalColors m_colors;
1640@@ -95,8 +98,9 @@
1641
1642 //TODO: vRince create some class to manage control/value
1643 //ControlConnection
1644- ControlObjectThreadMain* m_playPosControlObject;
1645+ VisualPlayPosition* m_visualPlayPosition;
1646 double m_playPos;
1647+ int m_playPosVSample;
1648 ControlObjectThreadMain* m_rateControlObject;
1649 double m_rate;
1650 ControlObjectThreadMain* m_rateRangeControlObject;
1651@@ -117,7 +121,6 @@
1652 int currentFrame;
1653 #endif
1654
1655- WaveformWidgetRenderer();
1656 private:
1657 DISALLOW_COPY_AND_ASSIGN(WaveformWidgetRenderer);
1658 friend class WaveformWidgetFactory;
1659
1660=== added file 'mixxx/src/waveform/vsyncthread.cpp'
1661--- mixxx/src/waveform/vsyncthread.cpp 1970-01-01 00:00:00 +0000
1662+++ mixxx/src/waveform/vsyncthread.cpp 2013-05-01 22:08:27 +0000
1663@@ -0,0 +1,179 @@
1664+
1665+#include <QThread>
1666+#include <QGLWidget>
1667+#include <QGLFormat>
1668+#include <QTime>
1669+#include <qdebug.h>
1670+#include <QTime>
1671+
1672+#include "mathstuff.h"
1673+#include "vsyncthread.h"
1674+#include "util/performancetimer.h"
1675+
1676+#if defined(__APPLE__)
1677+
1678+#elif defined(__WINDOWS__)
1679+
1680+#else
1681+ extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
1682+#endif
1683+
1684+VSyncThread::VSyncThread(QWidget* parent)
1685+ : QThread(),
1686+ m_firstRun(false),
1687+ m_usSyncTime(33333),
1688+ m_vSyncMode(ST_TIMER),
1689+ m_syncOk(false),
1690+ m_rtErrorCnt(0),
1691+ m_swapWait(0),
1692+ m_displayFrameRate(60.0),
1693+ m_interval(1) {
1694+ doRendering = true;
1695+}
1696+
1697+VSyncThread::~VSyncThread() {
1698+ doRendering = false;
1699+ m_sema.release(2); // Two slots
1700+ wait();
1701+ //delete m_glw;
1702+}
1703+
1704+void VSyncThread::stop()
1705+{
1706+ doRendering = false;
1707+}
1708+
1709+
1710+void VSyncThread::run() {
1711+ QThread::currentThread()->setObjectName("VSyncThread");
1712+
1713+ int usRest;
1714+ int usLast;
1715+
1716+ m_usWait = m_usSyncTime;
1717+ m_timer.start();
1718+
1719+ while (doRendering) {
1720+ if (m_vSyncMode == ST_FREE) {
1721+ // for benchmark only!
1722+ emit(vsync1()); // renders the waveform, Possible delayed due to anti tearing
1723+ m_sema.acquire();
1724+ emit(vsync2()); // swaps the new waveform to front
1725+ m_sema.acquire();
1726+ m_timer.restart();
1727+ m_usWait = 1000;
1728+ usleep(1000);
1729+ } else { // if (m_vSyncMode == ST_TIMER) {
1730+ usRest = m_usWait - m_timer.elapsed() / 1000;
1731+ // waiting for interval by sleep
1732+ if (usRest > 100) {
1733+ usleep(usRest);
1734+ }
1735+
1736+ emit(vsync2()); // swaps the new waveform to front in case of gl-wf
1737+ m_sema.acquire(); // wait until swap was scheduled. It might be delayed due to driver vSync settings
1738+ // <- Assume we are VSynced here ->
1739+ usLast = m_timer.restart() / 1000;
1740+ if (usRest < 0) {
1741+ // Our swapping call was already delayed
1742+ // The real swap might happens on the following VSync, depending on driver settings
1743+ m_rtErrorCnt++; // Count as Real Time Error
1744+ }
1745+ // try to stay in right intervals
1746+ usRest = m_usWait - usLast;
1747+ m_usWait = m_usSyncTime + (usRest % m_usSyncTime);
1748+ emit(vsync1()); // renders the new waveform.
1749+ m_sema.acquire(); // wait until rendreing was scheduled. It might be delayed due a pending swap (depends one driver vSync settings)
1750+ // qDebug() << "ST_TIMER " << usLast << usRest;
1751+ }
1752+ }
1753+}
1754+
1755+
1756+void VSyncThread::postRender(QGLWidget* glw, int index) {
1757+ // No need for glw->makeCurrent() here.
1758+// qDebug() << "postRender" << m_timer.elapsed();
1759+#if defined(__APPLE__)
1760+ glw->swapBuffers();
1761+#elif defined(__WINDOWS__)
1762+ glw->swapBuffers();
1763+#else
1764+ const QX11Info *xinfo = qt_x11Info(glw);
1765+ glXSwapBuffers(xinfo->display(), glw->winId());
1766+#endif
1767+}
1768+
1769+int VSyncThread::elapsed() {
1770+ return m_timer.elapsed() / 1000;
1771+}
1772+
1773+void VSyncThread::setUsSyncTime(int syncTime) {
1774+ m_usSyncTime = syncTime;
1775+ double frameRate = 60.0;
1776+ m_interval = round(m_displayFrameRate * m_usSyncTime / 1000);
1777+}
1778+
1779+void VSyncThread::setVSyncType(int type) {
1780+ if (type >= (int)VSyncThread::ST_COUNT) {
1781+ type = VSyncThread::ST_TIMER;
1782+ }
1783+ m_vSyncMode = (enum VSyncMode)type;
1784+ m_rtErrorCnt = 0;
1785+ m_firstRun = true;
1786+}
1787+
1788+int VSyncThread::usToNextSync() {
1789+ int usRest = m_usWait - m_timer.elapsed() / 1000;
1790+ if (usRest < 0) {
1791+ usRest %= m_usSyncTime;
1792+ usRest += m_usSyncTime;
1793+ }
1794+ return usRest;
1795+}
1796+
1797+int VSyncThread::usFromTimerToNextSync(PerformanceTimer* timer) {
1798+ int difference = m_timer.difference(timer) / 1000;
1799+ return difference + m_usWait;
1800+}
1801+
1802+int VSyncThread::rtErrorCnt() {
1803+ return m_rtErrorCnt;
1804+}
1805+
1806+void VSyncThread::vsyncSlotFinished() {
1807+ m_sema.release();
1808+}
1809+
1810+void VSyncThread::getAvailableVSyncTypes(QList<QPair<int, QString > >* pList) {
1811+ QPair<int, QString > pair;
1812+
1813+ for (int i = (int)VSyncThread::ST_TIMER; i < (int)VSyncThread::ST_COUNT; i++) {
1814+ //if (isAvailable(type)) // TODO
1815+ {
1816+ enum VSyncMode mode = (enum VSyncMode)i;
1817+
1818+ QString name;
1819+ switch (mode) {
1820+ case VSyncThread::ST_TIMER:
1821+ name = tr("Timer (Fallback)");
1822+ break;
1823+ case VSyncThread::ST_MESA_VBLANK_MODE_1:
1824+ name = tr("MESA vblank_mode = 1");
1825+ break;
1826+ case VSyncThread::ST_SGI_VIDEO_SYNC:
1827+ name = tr("Wait for Video sync");
1828+ break;
1829+ case VSyncThread::ST_OML_SYNC_CONTROL:
1830+ name = tr("Sync Control");
1831+ break;
1832+ case VSyncThread::ST_FREE:
1833+ name = tr("Free + 1 ms (for benchmark only)");
1834+ break;
1835+ default:
1836+ break;
1837+ }
1838+ QPair<int, QString > pair = QPair<int, QString >(i, name);
1839+ pList->append(pair);
1840+ }
1841+ }
1842+}
1843
1844=== added file 'mixxx/src/waveform/vsyncthread.h'
1845--- mixxx/src/waveform/vsyncthread.h 1970-01-01 00:00:00 +0000
1846+++ mixxx/src/waveform/vsyncthread.h 2013-05-01 22:08:27 +0000
1847@@ -0,0 +1,109 @@
1848+#ifndef VSYNCTHREAD_H
1849+#define VSYNCTHREAD_H
1850+
1851+#include <QTime>
1852+#include <QThread>
1853+#include <QSemaphore>
1854+#include <QPair>
1855+
1856+#include <qx11info_x11.h>
1857+#include "util/performancetimer.h"
1858+
1859+
1860+#if defined(__APPLE__)
1861+
1862+#elif defined(__WINDOWS__)
1863+
1864+#else
1865+ #include <GL/glx.h>
1866+ #include "GL/glxext.h"
1867+#endif
1868+
1869+
1870+class QGLWidget;
1871+
1872+class VSyncThread : public QThread {
1873+ Q_OBJECT
1874+ public:
1875+ enum VSyncMode {
1876+ ST_TIMER = 0,
1877+ ST_MESA_VBLANK_MODE_1,
1878+ ST_SGI_VIDEO_SYNC,
1879+ ST_OML_SYNC_CONTROL,
1880+ ST_FREE,
1881+ ST_COUNT // Dummy Type at last, counting possible types
1882+ };
1883+
1884+ VSyncThread(QWidget* parent);
1885+ ~VSyncThread();
1886+ void run();
1887+ void stop();
1888+
1889+ bool waitForVideoSync(QGLWidget* glw);
1890+ int elapsed();
1891+ int usToNextSync();
1892+ void setUsSyncTime(int usSyncTimer);
1893+ void setVSyncType(int mode);
1894+ int rtErrorCnt();
1895+ void setSwapWait(int sw);
1896+ int usFromTimerToNextSync(PerformanceTimer* timer);
1897+ void vsyncSlotFinished();
1898+ void getAvailableVSyncTypes(QList<QPair<int, QString > >* list);
1899+ void setupSync(QGLWidget* glw, int index);
1900+ void postRender(QGLWidget* glw, int index);
1901+ void waitUntilSwap(QGLWidget* glw);
1902+
1903+ signals:
1904+ void vsync1();
1905+ void vsync2();
1906+
1907+ private:
1908+ bool doRendering;
1909+ QGLWidget *m_glw;
1910+
1911+#if defined(__APPLE__)
1912+
1913+#elif defined(__WINDOWS__)
1914+
1915+#else
1916+ void initGlxext(QGLWidget* glw);
1917+ bool glXExtensionSupported(Display *dpy, int screen, const char *extension);
1918+
1919+ PFNGLXGETVIDEOSYNCSGIPROC glXGetVideoSyncSGI;
1920+ PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI;
1921+
1922+ PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;
1923+
1924+ PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
1925+
1926+ PFNGLXGETSYNCVALUESOMLPROC glXGetSyncValuesOML;
1927+ PFNGLXGETMSCRATEOMLPROC glXGetMscRateOML;
1928+ PFNGLXSWAPBUFFERSMSCOMLPROC glXSwapBuffersMscOML;
1929+ PFNGLXWAITFORMSCOMLPROC glXWaitForMscOML;
1930+ PFNGLXWAITFORSBCOMLPROC glXWaitForSbcOML;
1931+
1932+ PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalMESA;
1933+
1934+ uint m_counter;
1935+
1936+ int64_t m_target_msc;
1937+ Display* m_dpy;
1938+ GLXDrawable m_drawable;
1939+
1940+#endif
1941+
1942+ bool m_firstRun;
1943+ int m_usSyncTime;
1944+ int m_usWait;
1945+ enum VSyncMode m_vSyncMode;
1946+ bool m_syncOk;
1947+ int m_rtErrorCnt;
1948+ int m_swapWait;
1949+ PerformanceTimer m_timer;
1950+ QSemaphore m_sema;
1951+ double m_displayFrameRate;
1952+ int m_interval;
1953+};
1954+
1955+
1956+#endif // VSYNCTHREAD_H
1957
1958=== modified file 'mixxx/src/waveform/waveformwidgetfactory.cpp'
1959--- mixxx/src/waveform/waveformwidgetfactory.cpp 2012-12-13 22:46:16 +0000
1960+++ mixxx/src/waveform/waveformwidgetfactory.cpp 2013-05-01 22:08:27 +0000
1961@@ -18,8 +18,13 @@
1962 #include "waveform/widgets/qtwaveformwidget.h"
1963 #include "waveform/widgets/qtsimplewaveformwidget.h"
1964 #include "waveform/widgets/glslwaveformwidget.h"
1965+#include "waveform/widgets/glvsynctestwidget.h"
1966 #include "waveform/widgets/waveformwidgetabstract.h"
1967 #include "widget/wwaveformviewer.h"
1968+#include "waveform/vsyncthread.h"
1969+#include "util/cmdlineargs.h"
1970+
1971+#include "util/performancetimer.h"
1972 #include "util/timer.h"
1973
1974 ///////////////////////////////////////////
1975@@ -31,6 +36,12 @@
1976
1977 ///////////////////////////////////////////
1978
1979+WaveformWidgetHolder::WaveformWidgetHolder()
1980+ : m_waveformWidget(NULL),
1981+ m_waveformViewer(NULL),
1982+ m_visualNodeCache(QDomNode()) {
1983+}
1984+
1985 WaveformWidgetHolder::WaveformWidgetHolder(WaveformWidgetAbstract* waveformWidget,
1986 WWaveformViewer* waveformViewer,
1987 const QDomNode& visualNodeCache)
1988@@ -51,8 +62,8 @@
1989 m_overviewNormalized(false),
1990 m_openGLAvailable(false),
1991 m_openGLShaderAvailable(false),
1992- m_time(new QTime()),
1993- m_lastFrameTime(0),
1994+ m_vsyncThread(NULL),
1995+ m_frameCnt(0),
1996 m_actualFrameRate(0) {
1997
1998 m_visualGain[All] = 1.5;
1999@@ -129,17 +140,20 @@
2000 }
2001
2002 evaluateWidgets();
2003- start();
2004+ m_time.start();
2005 }
2006
2007 WaveformWidgetFactory::~WaveformWidgetFactory() {
2008- delete m_time;
2009+ if (m_vsyncThread) {
2010+ delete m_vsyncThread;
2011+ }
2012 }
2013
2014-bool WaveformWidgetFactory::setConfig(ConfigObject<ConfigValue> *config){
2015+bool WaveformWidgetFactory::setConfig(ConfigObject<ConfigValue> *config) {
2016 m_config = config;
2017- if (!m_config)
2018+ if (!m_config) {
2019 return false;
2020+ }
2021
2022 bool ok = false;
2023
2024@@ -150,6 +164,9 @@
2025 m_config->set(ConfigKey("[Waveform]","FrameRate"), ConfigValue(m_frameRate));
2026 }
2027
2028+ int vsync = m_config->getValueString(ConfigKey("[Waveform]","VSync"),"0").toInt();
2029+ setVSyncType(vsync);
2030+
2031 int defaultZoom = m_config->getValueString(ConfigKey("[Waveform]","DefaultZoom")).toInt(&ok);
2032 if (ok) {
2033 setDefaultZoom(defaultZoom);
2034@@ -192,25 +209,8 @@
2035 return true;
2036 }
2037
2038-void WaveformWidgetFactory::start() {
2039- //qDebug() << "WaveformWidgetFactory::start";
2040- killTimer(m_mainTimerId);
2041- m_mainTimerId = startTimer(1000.0/double(m_frameRate));
2042-}
2043-
2044-void WaveformWidgetFactory::stop() {
2045- killTimer(m_mainTimerId);
2046- m_mainTimerId = -1;
2047-}
2048-
2049-void WaveformWidgetFactory::timerEvent(QTimerEvent *timerEvent) {
2050- if (timerEvent->timerId() == m_mainTimerId) {
2051- refresh();
2052- }
2053-}
2054-
2055 void WaveformWidgetFactory::destroyWidgets() {
2056- for (unsigned int i = 0; i < m_waveformWidgetHolders.size(); i++) {
2057+ for (int i = 0; i < m_waveformWidgetHolders.size(); i++) {
2058 WaveformWidgetAbstract* pWidget = m_waveformWidgetHolders[i].m_waveformWidget;;
2059 m_waveformWidgetHolders[i].m_waveformWidget = NULL;
2060 delete pWidget;
2061@@ -247,6 +247,7 @@
2062 }
2063
2064 viewer->setZoom(m_defaultZoom);
2065+ viewer->update();
2066
2067 qDebug() << "WaveformWidgetFactory::setWaveformWidget - waveform widget added in factory, index" << index;
2068
2069@@ -254,11 +255,25 @@
2070 }
2071
2072 void WaveformWidgetFactory::setFrameRate(int frameRate) {
2073- m_frameRate = math_min(60, math_max(10, frameRate));
2074+ m_frameRate = math_min(120, math_max(1, frameRate));
2075 if (m_config) {
2076 m_config->set(ConfigKey("[Waveform]","FrameRate"), ConfigValue(m_frameRate));
2077 }
2078- start();
2079+ m_vsyncThread->setUsSyncTime(1000000/m_frameRate);
2080+}
2081+
2082+
2083+void WaveformWidgetFactory::setVSyncType(int type) {
2084+ if (m_config) {
2085+ m_config->set(ConfigKey("[Waveform]","VSync"), ConfigValue((int)type));
2086+ }
2087+
2088+ m_vSyncType = type;
2089+ m_vsyncThread->setVSyncType(type);
2090+}
2091+
2092+int WaveformWidgetFactory::getVSyncType() {
2093+ return m_vSyncType;
2094 }
2095
2096 bool WaveformWidgetFactory::setWidgetType(WaveformWidgetType::Type type) {
2097@@ -266,7 +281,7 @@
2098 return true;
2099
2100 // check if type is acceptable
2101- for (unsigned int i = 0; i < m_waveformWidgetHandles.size(); i++) {
2102+ for (int i = 0; i < m_waveformWidgetHandles.size(); i++) {
2103 WaveformWidgetAbstractHandle& handle = m_waveformWidgetHandles[i];
2104 if (handle.m_type == type) {
2105 // type is acceptable
2106@@ -307,7 +322,7 @@
2107 //qDebug() << "recreate start";
2108
2109 //re-create/setup all waveform widgets
2110- for (unsigned int i = 0; i < m_waveformWidgetHolders.size(); i++) {
2111+ for (int i = 0; i < m_waveformWidgetHolders.size(); i++) {
2112 WaveformWidgetHolder& holder = m_waveformWidgetHolders[i];
2113 WaveformWidgetAbstract* previousWidget = holder.m_waveformWidget;
2114 TrackPointer pTrack = previousWidget->getTrackInfo();
2115@@ -325,6 +340,8 @@
2116 //viewer->resize(viewer->size());
2117 widget->resize(viewer->width(), viewer->height());
2118 widget->setTrack(pTrack);
2119+ widget->getWidget()->show();
2120+ viewer->update();
2121 }
2122
2123 m_skipRender = false;
2124@@ -339,7 +356,7 @@
2125 m_config->set(ConfigKey("[Waveform]","DefaultZoom"), ConfigValue(m_defaultZoom));
2126 }
2127
2128- for (unsigned int i = 0; i < m_waveformWidgetHolders.size(); i++) {
2129+ for (int i = 0; i < m_waveformWidgetHolders.size(); i++) {
2130 m_waveformWidgetHolders[i].m_waveformViewer->setZoom(m_defaultZoom);
2131 }
2132 }
2133@@ -355,7 +372,7 @@
2134 }
2135
2136 int refZoom = m_waveformWidgetHolders[0].m_waveformWidget->getZoomFactor();
2137- for (unsigned int i = 1; i < m_waveformWidgetHolders.size(); i++) {
2138+ for (int i = 1; i < m_waveformWidgetHolders.size(); i++) {
2139 m_waveformWidgetHolders[i].m_waveformViewer->setZoom(refZoom);
2140 }
2141 }
2142@@ -390,29 +407,67 @@
2143 }
2144
2145 void WaveformWidgetFactory::refresh() {
2146- if (m_skipRender)
2147- return;
2148-
2149 ScopedTimer t(QString("WaveformWidgetFactory::refresh() %1waveforms")
2150- .arg(m_waveformWidgetHolders.size()));
2151-
2152- for (unsigned int i = 0; i < m_waveformWidgetHolders.size(); i++)
2153- m_waveformWidgetHolders[i].m_waveformWidget->preRender();
2154-
2155- for (unsigned int i = 0; i < m_waveformWidgetHolders.size(); i++)
2156- m_waveformWidgetHolders[i].m_waveformWidget->render();
2157-
2158- for (unsigned int i = 0; i < m_waveformWidgetHolders.size(); i++)
2159- m_waveformWidgetHolders[i].m_waveformWidget->postRender();
2160-
2161- // Notify all other waveform-like widgets (e.g. WSpinny's) that they should
2162- // update.
2163- emit(waveformUpdateTick());
2164-
2165- m_lastFrameTime = m_time->restart();
2166- if (m_lastFrameTime && m_lastFrameTime <= 1000) {
2167- m_actualFrameRate = 1000.0/(double)(m_lastFrameTime);
2168- }
2169+ .arg(m_waveformWidgetHolders.size()));
2170+
2171+ int paintersSetupTime0 = 0;
2172+ int paintersSetupTime1 = 0;
2173+
2174+ if (!m_skipRender) {
2175+ if (m_type) { // no regular updates for an empty waveform
2176+ // next rendered frame is displayed after next buffer swap and than after VSync
2177+ for (int i = 0; i < m_waveformWidgetHolders.size(); i++) {
2178+ // Calculate play position for the new Frame in following run
2179+ m_waveformWidgetHolders[i].m_waveformWidget->preRender(m_vsyncThread);
2180+ }
2181+ //qDebug() << "prerender" << m_vsyncThread->elapsed();
2182+
2183+ // It may happen that there is an artificially delayed due to
2184+ // anti tearing driver settings
2185+ // all render commands are delayed until the swap from the previous run is executed
2186+ for (int i = 0; i < m_waveformWidgetHolders.size(); i++) {
2187+ (void)m_waveformWidgetHolders[i].m_waveformWidget->render();
2188+ // qDebug() << "render" << i << m_vsyncThread->elapsed();
2189+ }
2190+ }
2191+
2192+ // Notify all other waveform-like widgets (e.g. WSpinny's) that they should
2193+ // update.
2194+ //int t1 = m_vsyncThread->elapsed();
2195+ emit(waveformUpdateTick());
2196+ //qDebug() << "emit" << m_vsyncThread->elapsed() - t1;
2197+
2198+ m_frameCnt += 1.0;
2199+ int timeCnt = m_time.elapsed();
2200+ if (timeCnt > 1000) {
2201+ m_time.start();
2202+ m_frameCnt = m_frameCnt * 1000 / timeCnt; // latency correction
2203+ emit(waveformMeasured(m_frameCnt, m_vsyncThread->rtErrorCnt()));
2204+ m_frameCnt = 0.0;
2205+ }
2206+ }
2207+ //qDebug() << "refresh end" << m_vsyncThread->elapsed();
2208+ m_vsyncThread->vsyncSlotFinished();
2209+}
2210+
2211+void WaveformWidgetFactory::postRefresh() {
2212+ // Do this in an extra slot to be sure to hit the desired interval
2213+ if (!m_skipRender) {
2214+ if (m_type) { // no regular updates for an empty waveform
2215+ // Show rendered buffer from last refresh() run
2216+ //qDebug() << "postRefresh start" << m_vsyncThread->elapsed();
2217+ for (int i = 0; i < m_waveformWidgetHolders.size(); i++) {
2218+ QGLWidget* glw = dynamic_cast<QGLWidget*>(
2219+ m_waveformWidgetHolders[i].m_waveformWidget->getWidget());
2220+ if (glw) {
2221+ m_vsyncThread->postRender(glw, i);
2222+ }
2223+ //qDebug() << "postRefresh x" << m_vsyncThread->elapsed();
2224+ }
2225+ }
2226+ }
2227+ //qDebug() << "postRefresh end" << m_vsyncThread->elapsed();
2228+ m_vsyncThread->vsyncSlotFinished();
2229 }
2230
2231 WaveformWidgetType::Type WaveformWidgetFactory::autoChooseWidgetType() const {
2232@@ -435,12 +490,14 @@
2233 QString widgetName;
2234 bool useOpenGl;
2235 bool useOpenGLShaders;
2236+ bool developerOnly;
2237
2238 switch(type) {
2239 case WaveformWidgetType::EmptyWaveform:
2240 widgetName = EmptyWaveformWidget::getWaveformWidgetName();
2241 useOpenGl = EmptyWaveformWidget::useOpenGl();
2242 useOpenGLShaders = EmptyWaveformWidget::useOpenGLShaders();
2243+ developerOnly = EmptyWaveformWidget::developerOnly();
2244 break;
2245 case WaveformWidgetType::SoftwareSimpleWaveform:
2246 continue; // //TODO(vrince):
2247@@ -448,37 +505,52 @@
2248 widgetName = SoftwareWaveformWidget::getWaveformWidgetName();
2249 useOpenGl = SoftwareWaveformWidget::useOpenGl();
2250 useOpenGLShaders = SoftwareWaveformWidget::useOpenGLShaders();
2251+ developerOnly = SoftwareWaveformWidget::developerOnly();
2252 break;
2253 case WaveformWidgetType::HSVWaveform:
2254 widgetName = HSVWaveformWidget::getWaveformWidgetName();
2255 useOpenGl = HSVWaveformWidget::useOpenGl();
2256 useOpenGLShaders = HSVWaveformWidget::useOpenGLShaders();
2257+ developerOnly = HSVWaveformWidget::developerOnly();
2258 break;
2259 case WaveformWidgetType::QtSimpleWaveform:
2260 widgetName = QtSimpleWaveformWidget::getWaveformWidgetName();
2261 useOpenGl = QtSimpleWaveformWidget::useOpenGl();
2262 useOpenGLShaders = QtSimpleWaveformWidget::useOpenGLShaders();
2263+ developerOnly = QtSimpleWaveformWidget::developerOnly();
2264 break;
2265 case WaveformWidgetType::QtWaveform:
2266 widgetName = QtWaveformWidget::getWaveformWidgetName();
2267 useOpenGl = QtWaveformWidget::useOpenGl();
2268 useOpenGLShaders = QtWaveformWidget::useOpenGLShaders();
2269+ developerOnly = QtWaveformWidget::developerOnly();
2270 break;
2271 case WaveformWidgetType::GLSimpleWaveform:
2272 widgetName = GLSimpleWaveformWidget::getWaveformWidgetName();
2273 useOpenGl = GLSimpleWaveformWidget::useOpenGl();
2274 useOpenGLShaders = GLSimpleWaveformWidget::useOpenGLShaders();
2275+ developerOnly = GLSimpleWaveformWidget::developerOnly();
2276 break;
2277 case WaveformWidgetType::GLWaveform:
2278 widgetName = GLWaveformWidget::getWaveformWidgetName();
2279 useOpenGl = GLWaveformWidget::useOpenGl();
2280 useOpenGLShaders = GLWaveformWidget::useOpenGLShaders();
2281+ developerOnly = GLWaveformWidget::developerOnly();
2282 break;
2283 case WaveformWidgetType::GLSLWaveform:
2284 widgetName = GLSLWaveformWidget::getWaveformWidgetName();
2285 useOpenGl = GLSLWaveformWidget::useOpenGl();
2286 useOpenGLShaders = GLSLWaveformWidget::useOpenGLShaders();
2287- break;
2288+ developerOnly = GLSLWaveformWidget::developerOnly();
2289+ break;
2290+ case WaveformWidgetType::GLVSyncTest:
2291+ widgetName = GLVSyncTestWidget::getWaveformWidgetName();
2292+ useOpenGl = GLVSyncTestWidget::useOpenGl();
2293+ useOpenGLShaders = GLVSyncTestWidget::useOpenGLShaders();
2294+ developerOnly = GLVSyncTestWidget::developerOnly();
2295+ break;
2296+ default:
2297+ continue;
2298 }
2299
2300 if (useOpenGLShaders) {
2301@@ -499,6 +571,12 @@
2302 handle.m_active = false;
2303 continue;
2304 }
2305+
2306+ if (developerOnly && !CmdlineArgs::Instance().getDeveloper()) {
2307+ handle.m_active = false;
2308+ continue;
2309+ }
2310+
2311 m_waveformWidgetHandles.push_back(handle);
2312 }
2313 }
2314@@ -529,6 +607,9 @@
2315 case WaveformWidgetType::GLSLWaveform:
2316 widget = new GLSLWaveformWidget(viewer->getGroup(), viewer);
2317 break;
2318+ case WaveformWidgetType::GLVSyncTest:
2319+ widget = new GLVSyncTestWidget(viewer->getGroup(), viewer);
2320+ break;
2321 default:
2322 //case WaveformWidgetType::SoftwareSimpleWaveform: TODO: (vrince)
2323 //case WaveformWidgetType::EmptyWaveform:
2324@@ -552,8 +633,32 @@
2325 }
2326
2327 int WaveformWidgetFactory::findIndexOf(WWaveformViewer* viewer) const {
2328- for (int i = 0; i < (int)m_waveformWidgetHolders.size(); i++)
2329- if (m_waveformWidgetHolders[i].m_waveformViewer == viewer)
2330+ for (int i = 0; i < (int)m_waveformWidgetHolders.size(); i++) {
2331+ if (m_waveformWidgetHolders[i].m_waveformViewer == viewer) {
2332 return i;
2333+ }
2334+ }
2335 return -1;
2336 }
2337+
2338+void WaveformWidgetFactory::startVSync(QWidget *parent) {
2339+ if (m_vsyncThread) {
2340+ disconnect(m_vsyncThread, SIGNAL(vsync1()), this, SLOT(refresh()));
2341+ disconnect(m_vsyncThread, SIGNAL(vsync2()), this, SLOT(postRefresh()));
2342+ delete m_vsyncThread;
2343+ }
2344+ m_vsyncThread = new VSyncThread(parent);
2345+ m_vsyncThread->start();
2346+
2347+ connect(m_vsyncThread, SIGNAL(vsync1()),
2348+ this, SLOT(refresh()));
2349+ connect(m_vsyncThread, SIGNAL(vsync2()),
2350+ this, SLOT(postRefresh()));
2351+
2352+}
2353+
2354+void WaveformWidgetFactory::getAvailableVSyncTypes(QList<QPair<int, QString > >* pList) {
2355+ m_vsyncThread->getAvailableVSyncTypes(pList);
2356+}
2357+
2358+
2359
2360=== modified file 'mixxx/src/waveform/waveformwidgetfactory.h'
2361--- mixxx/src/waveform/waveformwidgetfactory.h 2012-05-30 18:26:44 +0000
2362+++ mixxx/src/waveform/waveformwidgetfactory.h 2013-05-01 22:08:27 +0000
2363@@ -8,14 +8,15 @@
2364 #include "waveform/waveform.h"
2365
2366 #include <QObject>
2367-
2368-#include <vector>
2369+#include <QTime>
2370+#include <QVector>
2371
2372 class WWaveformViewer;
2373 class WaveformWidgetAbstract;
2374 class ControlObjectThreadMain;
2375 class QTimer;
2376-class QTime;
2377+class VSyncThread;
2378+
2379
2380 class WaveformWidgetAbstractHandle {
2381 public:
2382@@ -34,7 +35,9 @@
2383 };
2384
2385 class WaveformWidgetHolder {
2386-private:
2387+ public:
2388+ WaveformWidgetHolder();
2389+ private:
2390 WaveformWidgetHolder(WaveformWidgetAbstract* waveformWidget,
2391 WWaveformViewer* waveformViewer,
2392 const QDomNode& visualNodeCache);
2393@@ -62,7 +65,7 @@
2394
2395 void setFrameRate( int frameRate);
2396 int getFrameRate() const { return m_frameRate;}
2397- double getActualFrameRate() const { return m_actualFrameRate;}
2398+// bool getVSync() const { return m_vSyncType;}
2399
2400 bool isOpenGLAvailable() const { return m_openGLAvailable;}
2401 QString getOpenGLVersion() const { return m_openGLVersion;}
2402@@ -85,22 +88,21 @@
2403 void setOverviewNormalized(bool normalize);
2404 int isOverviewNormalized() const { return m_overviewNormalized;}
2405
2406- const std::vector<WaveformWidgetAbstractHandle> getAvailableTypes() const { return m_waveformWidgetHandles;}
2407+ const QVector<WaveformWidgetAbstractHandle> getAvailableTypes() const { return m_waveformWidgetHandles;}
2408+ void getAvailableVSyncTypes(QList<QPair<int, QString > >* list);
2409 void destroyWidgets();
2410
2411 void addTimerListener(QWidget* pWidget);
2412
2413- public slots:
2414- void start();
2415- void stop();
2416+ void startVSync(QWidget *parent);
2417+ void setVSyncType(int vsType);
2418+ int getVSyncType();
2419
2420 void notifyZoomChange(WWaveformViewer *viewer);
2421
2422 signals:
2423 void waveformUpdateTick();
2424-
2425- protected:
2426- void timerEvent(QTimerEvent *timerEvent);
2427+ void waveformMeasured(float frameRate, int rtErrorCnt);
2428
2429 protected:
2430 WaveformWidgetFactory();
2431@@ -110,6 +112,7 @@
2432
2433 private slots:
2434 void refresh();
2435+ void postRefresh();
2436
2437 private:
2438 WaveformWidgetType::Type autoChooseWidgetType() const;
2439@@ -118,10 +121,11 @@
2440 int findIndexOf( WWaveformViewer* viewer) const;
2441
2442 //All type of available widgets
2443- std::vector<WaveformWidgetAbstractHandle> m_waveformWidgetHandles;
2444+
2445+ QVector<WaveformWidgetAbstractHandle> m_waveformWidgetHandles;
2446
2447 //Currently in use widgets/visual/node
2448- std::vector<WaveformWidgetHolder> m_waveformWidgetHolders;
2449+ QVector<WaveformWidgetHolder> m_waveformWidgetHolders;
2450
2451 WaveformWidgetType::Type m_type;
2452
2453@@ -139,10 +143,17 @@
2454 QString m_openGLVersion;
2455 bool m_openGLShaderAvailable;
2456
2457+ VSyncThread* m_vsyncThread;
2458+
2459 //Debug
2460- QTime* m_time;
2461- int m_lastFrameTime;
2462+ QTime m_time;
2463+ QTime m_delayTime;
2464+ float m_frameCnt;
2465+ int m_lastRenderDuration;
2466 double m_actualFrameRate;
2467+ double m_minimumFrameRate;
2468+ double m_maximumlFrameRate;
2469+ int m_vSyncType;
2470 };
2471
2472 #endif // WAVEFORMWIDGETFACTORY_H
2473
2474=== modified file 'mixxx/src/waveform/widgets/emptywaveformwidget.cpp'
2475--- mixxx/src/waveform/widgets/emptywaveformwidget.cpp 2012-09-19 21:04:53 +0000
2476+++ mixxx/src/waveform/widgets/emptywaveformwidget.cpp 2013-05-01 22:08:27 +0000
2477@@ -25,6 +25,12 @@
2478 }
2479
2480 void EmptyWaveformWidget::paintEvent(QPaintEvent* event) {
2481+ // Only render if Qt thinks it is required
2482 QPainter painter(this);
2483 draw(&painter,event);
2484 }
2485+
2486+int EmptyWaveformWidget::render() {
2487+ // skip update every frame
2488+ return 0;
2489+}
2490
2491=== modified file 'mixxx/src/waveform/widgets/emptywaveformwidget.h'
2492--- mixxx/src/waveform/widgets/emptywaveformwidget.h 2012-09-19 21:04:53 +0000
2493+++ mixxx/src/waveform/widgets/emptywaveformwidget.h 2013-05-01 22:08:27 +0000
2494@@ -18,13 +18,14 @@
2495 static inline QString getWaveformWidgetName() { return tr("Empty"); }
2496 static inline bool useOpenGl() { return false; }
2497 static inline bool useOpenGLShaders() { return false; }
2498+ static inline bool developerOnly() { return false; }
2499
2500 protected:
2501 virtual void castToQWidget();
2502 virtual void paintEvent(QPaintEvent* event);
2503+ virtual int render();
2504
2505 private:
2506- EmptyWaveformWidget() {}
2507 EmptyWaveformWidget(const char* group, QWidget* parent);
2508 friend class WaveformWidgetFactory;
2509 };
2510
2511=== modified file 'mixxx/src/waveform/widgets/glsimplewaveformwidget.cpp'
2512--- mixxx/src/waveform/widgets/glsimplewaveformwidget.cpp 2013-01-04 20:29:33 +0000
2513+++ mixxx/src/waveform/widgets/glsimplewaveformwidget.cpp 2013-05-01 22:08:27 +0000
2514@@ -13,6 +13,8 @@
2515 #include "waveform/renderers/waveformrendererendoftrack.h"
2516 #include "waveform/renderers/waveformrenderbeat.h"
2517
2518+#include "util/performancetimer.h"
2519+
2520 GLSimpleWaveformWidget::GLSimpleWaveformWidget( const char* group, QWidget* parent)
2521 : QGLWidget(parent, SharedGLContext::getWidget()),
2522 WaveformWidgetAbstract(group) {
2523@@ -49,11 +51,24 @@
2524 }
2525
2526 void GLSimpleWaveformWidget::paintEvent( QPaintEvent* event) {
2527- if (QGLContext::currentContext() != context()) {
2528- makeCurrent();
2529- }
2530+ Q_UNUSED(event);
2531+}
2532+
2533+int GLSimpleWaveformWidget::render() {
2534+ PerformanceTimer timer;
2535+ int t1;
2536+ //int t2, t3;
2537+ timer.start();
2538+ // QPainter makes QGLContext::currentContext() == context()
2539+ // this may delayed until previous buffer swap finished
2540 QPainter painter(this);
2541- draw(&painter,event);
2542+ t1 = timer.restart();
2543+ draw(&painter, NULL);
2544+ //t2 = timer.restart();
2545+ //glFinish();
2546+ //t3 = timer.restart();
2547+ //qDebug() << "GLVSyncTestWidget "<< t1 << t2 << t3;
2548+ return t1 / 1000; // return timer for painter setup
2549 }
2550
2551 void GLSimpleWaveformWidget::postRender() {
2552
2553=== modified file 'mixxx/src/waveform/widgets/glsimplewaveformwidget.h'
2554--- mixxx/src/waveform/widgets/glsimplewaveformwidget.h 2012-09-19 21:04:53 +0000
2555+++ mixxx/src/waveform/widgets/glsimplewaveformwidget.h 2013-05-01 22:08:27 +0000
2556@@ -11,19 +11,20 @@
2557 GLSimpleWaveformWidget(const char* group, QWidget* parent);
2558 virtual ~GLSimpleWaveformWidget();
2559
2560- virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::GLSimpleWaveform;}
2561+ virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::GLSimpleWaveform; }
2562
2563- static inline QString getWaveformWidgetName() { return tr("Simple");}
2564- static inline bool useOpenGl() { return true;}
2565- static inline bool useOpenGLShaders() { return false;}
2566+ static inline QString getWaveformWidgetName() { return tr("Simple"); }
2567+ static inline bool useOpenGl() { return true; }
2568+ static inline bool useOpenGLShaders() { return false; }
2569+ static inline bool developerOnly() { return false; }
2570
2571 protected:
2572 virtual void castToQWidget();
2573 virtual void paintEvent(QPaintEvent* event);
2574 virtual void postRender();
2575+ virtual int render();
2576
2577 private:
2578- GLSimpleWaveformWidget() {}
2579 friend class WaveformWidgetFactory;
2580 };
2581 #endif // GLSIMPLEWAVEFORMWIDGET_H
2582
2583=== modified file 'mixxx/src/waveform/widgets/glslwaveformwidget.cpp'
2584--- mixxx/src/waveform/widgets/glslwaveformwidget.cpp 2013-01-04 20:29:33 +0000
2585+++ mixxx/src/waveform/widgets/glslwaveformwidget.cpp 2013-05-01 22:08:27 +0000
2586@@ -13,6 +13,8 @@
2587 #include "waveform/renderers/waveformrenderbeat.h"
2588 #include "sharedglcontext.h"
2589
2590+#include "util/performancetimer.h"
2591+
2592 GLSLWaveformWidget::GLSLWaveformWidget( const char* group, QWidget* parent)
2593 : QGLWidget(parent, SharedGLContext::getWidget()),
2594 WaveformWidgetAbstract(group) {
2595@@ -48,10 +50,24 @@
2596 }
2597
2598 void GLSLWaveformWidget::paintEvent( QPaintEvent* event) {
2599- makeCurrent();
2600+ Q_UNUSED(event);
2601+}
2602+
2603+int GLSLWaveformWidget::render() {
2604+ PerformanceTimer timer;
2605+ int t1;
2606+ //int t2, t3;
2607+ timer.start();
2608+ // QPainter makes QGLContext::currentContext() == context()
2609+ // this may delayed until previous buffer swap finished
2610 QPainter painter(this);
2611- draw(&painter,event);
2612- QGLWidget::swapBuffers();
2613+ t1 = timer.restart();
2614+ draw(&painter, NULL);
2615+ //t2 = timer.restart();
2616+ //glFinish();
2617+ //t3 = timer.restart();
2618+ //qDebug() << "GLVSyncTestWidget "<< t1 << t2 << t3;
2619+ return t1 / 1000; // return timer for painter setup
2620 }
2621
2622 void GLSLWaveformWidget::resize( int width, int height) {
2623@@ -67,3 +83,7 @@
2624 signalRenderer_->loadShaders();
2625 }
2626 }
2627+
2628+void GLSLWaveformWidget::postRender() {
2629+ swapBuffers();
2630+}
2631
2632=== modified file 'mixxx/src/waveform/widgets/glslwaveformwidget.h'
2633--- mixxx/src/waveform/widgets/glslwaveformwidget.h 2012-12-06 06:35:21 +0000
2634+++ mixxx/src/waveform/widgets/glslwaveformwidget.h 2013-05-01 22:08:27 +0000
2635@@ -13,11 +13,12 @@
2636 GLSLWaveformWidget(const char* group, QWidget* parent);
2637 virtual ~GLSLWaveformWidget();
2638
2639- virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::GLSLWaveform;}
2640+ virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::GLSLWaveform; }
2641
2642- static inline QString getWaveformWidgetName() { return tr("Filtered") + " - " + tr("experimental");}
2643- static inline bool useOpenGl() { return true;}
2644- static inline bool useOpenGLShaders() { return true;}
2645+ static inline QString getWaveformWidgetName() { return tr("Filtered") + " - " + tr("experimental"); }
2646+ static inline bool useOpenGl() { return true; }
2647+ static inline bool useOpenGLShaders() { return true; }
2648+ static inline bool developerOnly() { return false; }
2649
2650 virtual void resize(int width, int height);
2651
2652@@ -25,11 +26,12 @@
2653 virtual void castToQWidget();
2654 virtual void paintEvent(QPaintEvent* event);
2655 virtual void mouseDoubleClickEvent(QMouseEvent *);
2656+ virtual void postRender();
2657+ virtual int render();
2658
2659 private:
2660 GLSLWaveformRendererSignal* signalRenderer_;
2661
2662- GLSLWaveformWidget() {}
2663 friend class WaveformWidgetFactory;
2664 };
2665
2666
2667=== added file 'mixxx/src/waveform/widgets/glvsynctestwidget.cpp'
2668--- mixxx/src/waveform/widgets/glvsynctestwidget.cpp 1970-01-01 00:00:00 +0000
2669+++ mixxx/src/waveform/widgets/glvsynctestwidget.cpp 2013-05-01 22:08:27 +0000
2670@@ -0,0 +1,75 @@
2671+#include "glvsynctestwidget.h"
2672+
2673+#include <QPainter>
2674+
2675+#include "sharedglcontext.h"
2676+#include "waveform/renderers/waveformwidgetrenderer.h"
2677+#include "waveform/renderers/waveformrenderbackground.h"
2678+#include "waveform/renderers/glwaveformrenderersimplesignal.h"
2679+#include "waveform/renderers/glvsynctestrenderer.h"
2680+#include "waveform/renderers/waveformrendererpreroll.h"
2681+#include "waveform/renderers/waveformrendermark.h"
2682+#include "waveform/renderers/waveformrendermarkrange.h"
2683+#include "waveform/renderers/waveformrendererendoftrack.h"
2684+#include "waveform/renderers/waveformrenderbeat.h"
2685+
2686+#include "util/performancetimer.h"
2687+
2688+GLVSyncTestWidget::GLVSyncTestWidget( const char* group, QWidget* parent)
2689+ : QGLWidget(parent, SharedGLContext::getWidget()),
2690+ WaveformWidgetAbstract(group) {
2691+
2692+// addRenderer<WaveformRenderBackground>(); // 172 µs
2693+// addRenderer<WaveformRendererEndOfTrack>(); // 677 µs 1145 µs (active)
2694+// addRenderer<WaveformRendererPreroll>(); // 652 µs 2034 µs (active)
2695+// addRenderer<WaveformRenderMarkRange>(); // 793 µs
2696+ addRenderer<GLVSyncTestRenderer>(); // 841 µs // 2271 µs
2697+// addRenderer<WaveformRenderMark>(); // 711 µs
2698+// addRenderer<WaveformRenderBeat>(); // 1183 µs
2699+
2700+ setAttribute(Qt::WA_NoSystemBackground);
2701+ setAttribute(Qt::WA_OpaquePaintEvent);
2702+
2703+ setAutoBufferSwap(false);
2704+
2705+ if (QGLContext::currentContext() != context()) {
2706+ makeCurrent();
2707+ }
2708+ m_initSuccess = init();
2709+ qDebug() << "GLVSyncTestWidget.isSharing() =" << isSharing();
2710+}
2711+
2712+GLVSyncTestWidget::~GLVSyncTestWidget(){
2713+ if (QGLContext::currentContext() != context()) {
2714+ makeCurrent();
2715+ }
2716+}
2717+
2718+void GLVSyncTestWidget::castToQWidget() {
2719+ m_widget = static_cast<QWidget*>(static_cast<QGLWidget*>(this));
2720+}
2721+
2722+void GLVSyncTestWidget::paintEvent( QPaintEvent* event) {
2723+ Q_UNUSED(event);
2724+}
2725+
2726+int GLVSyncTestWidget::render() {
2727+ PerformanceTimer timer;
2728+ int t1;
2729+ //int t2, t3;
2730+ timer.start();
2731+ // QPainter makes QGLContext::currentContext() == context()
2732+ // this may delayed until previous buffer swap finished
2733+ QPainter painter(this);
2734+ t1 = timer.restart();
2735+ draw(&painter, NULL);
2736+ //t2 = timer.restart();
2737+ glFinish();
2738+ //t3 = timer.restart();
2739+ //qDebug() << "GLVSyncTestWidget "<< t1 << t2 << t3;
2740+ return t1 / 1000; // return timer for painter setup
2741+}
2742+
2743+void GLVSyncTestWidget::postRender() {
2744+ QGLWidget::swapBuffers();
2745+}
2746
2747=== added file 'mixxx/src/waveform/widgets/glvsynctestwidget.h'
2748--- mixxx/src/waveform/widgets/glvsynctestwidget.h 1970-01-01 00:00:00 +0000
2749+++ mixxx/src/waveform/widgets/glvsynctestwidget.h 2013-05-01 22:08:27 +0000
2750@@ -0,0 +1,30 @@
2751+#ifndef GLVSYNCTESTWIDGET_H
2752+#define GLVSYNCTESTWIDGET_H
2753+
2754+#include <QGLWidget>
2755+
2756+#include "waveformwidgetabstract.h"
2757+
2758+class GLVSyncTestWidget : public QGLWidget, public WaveformWidgetAbstract {
2759+ Q_OBJECT
2760+ public:
2761+ GLVSyncTestWidget(const char* group, QWidget* parent);
2762+ virtual ~GLVSyncTestWidget();
2763+
2764+ virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::GLVSyncTest; }
2765+
2766+ static inline QString getWaveformWidgetName() { return tr("VSyncTest"); }
2767+ static inline bool useOpenGl() { return true; }
2768+ static inline bool useOpenGLShaders() { return false; }
2769+ static inline bool developerOnly() { return true; }
2770+
2771+ protected:
2772+ virtual void castToQWidget();
2773+ virtual void paintEvent(QPaintEvent* event);
2774+ virtual void postRender();
2775+ virtual int render();
2776+
2777+ private:
2778+ friend class WaveformWidgetFactory;
2779+};
2780+#endif // GLVSYNCTESTWIDGET_H
2781
2782=== modified file 'mixxx/src/waveform/widgets/glwaveformwidget.cpp'
2783--- mixxx/src/waveform/widgets/glwaveformwidget.cpp 2013-01-04 20:29:33 +0000
2784+++ mixxx/src/waveform/widgets/glwaveformwidget.cpp 2013-05-01 22:08:27 +0000
2785@@ -13,6 +13,7 @@
2786 #include "waveform/renderers/waveformrendererendoftrack.h"
2787 #include "waveform/renderers/waveformrenderbeat.h"
2788 #include "sharedglcontext.h"
2789+#include "util/performancetimer.h"
2790
2791 GLWaveformWidget::GLWaveformWidget( const char* group, QWidget* parent)
2792 : QGLWidget(parent, SharedGLContext::getWidget()),
2793@@ -48,11 +49,24 @@
2794 }
2795
2796 void GLWaveformWidget::paintEvent( QPaintEvent* event) {
2797- if (QGLContext::currentContext() != context()) {
2798- makeCurrent();
2799- }
2800+ Q_UNUSED(event);
2801+}
2802+
2803+int GLWaveformWidget::render() {
2804+ PerformanceTimer timer;
2805+ int t1;
2806+ //int t2, t3;
2807+ timer.start();
2808+ // QPainter makes QGLContext::currentContext() == context()
2809+ // this may delayed until previous buffer swap finished
2810 QPainter painter(this);
2811- draw(&painter, event);
2812+ t1 = timer.restart();
2813+ draw(&painter, NULL);
2814+ //t2 = timer.restart();
2815+ // glFinish();
2816+ //t3 = timer.restart();
2817+ //qDebug() << "GLVSyncTestWidget "<< t1 << t2 << t3;
2818+ return t1 / 1000; // return timer for painter setup
2819 }
2820
2821 void GLWaveformWidget::postRender() {
2822
2823=== modified file 'mixxx/src/waveform/widgets/glwaveformwidget.h'
2824--- mixxx/src/waveform/widgets/glwaveformwidget.h 2012-12-06 06:35:21 +0000
2825+++ mixxx/src/waveform/widgets/glwaveformwidget.h 2013-05-01 22:08:27 +0000
2826@@ -13,17 +13,18 @@
2827
2828 virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::GLWaveform; }
2829
2830- static inline QString getWaveformWidgetName() { return tr("Filtered");}
2831- static inline bool useOpenGl() { return true;}
2832- static inline bool useOpenGLShaders() { return false;}
2833+ static inline QString getWaveformWidgetName() { return tr("Filtered"); }
2834+ static inline bool useOpenGl() { return true; }
2835+ static inline bool useOpenGLShaders() { return false; }
2836+ static inline bool developerOnly() { return false; }
2837
2838 protected:
2839 virtual void castToQWidget();
2840 virtual void paintEvent(QPaintEvent* event);
2841 virtual void postRender();
2842+ virtual int render();
2843
2844 private:
2845- GLWaveformWidget() {}
2846 friend class WaveformWidgetFactory;
2847 };
2848
2849
2850=== added file 'mixxx/src/waveform/widgets/hsvwaveformwidget.cpp'
2851--- mixxx/src/waveform/widgets/hsvwaveformwidget.cpp 1970-01-01 00:00:00 +0000
2852+++ mixxx/src/waveform/widgets/hsvwaveformwidget.cpp 2013-05-01 22:08:27 +0000
2853@@ -0,0 +1,41 @@
2854+#include "hsvwaveformwidget.h"
2855+
2856+#include <QPainter>
2857+
2858+#include "waveform/renderers/waveformwidgetrenderer.h"
2859+#include "waveform/renderers/waveformrenderbackground.h"
2860+#include "waveform/renderers/waveformrendermark.h"
2861+#include "waveform/renderers/waveformrendermarkrange.h"
2862+#include "waveform/renderers/waveformrendererhsv.h"
2863+#include "waveform/renderers/waveformrendererpreroll.h"
2864+#include "waveform/renderers/waveformrendererendoftrack.h"
2865+#include "waveform/renderers/waveformrenderbeat.h"
2866+
2867+HSVWaveformWidget::HSVWaveformWidget( const char* group, QWidget* parent)
2868+ : QWidget(parent),
2869+ WaveformWidgetAbstract(group) {
2870+ addRenderer<WaveformRenderBackground>();
2871+ addRenderer<WaveformRendererEndOfTrack>();
2872+ addRenderer<WaveformRendererPreroll>();
2873+ addRenderer<WaveformRenderMarkRange>();
2874+ addRenderer<WaveformRendererHSV>();
2875+ addRenderer<WaveformRenderMark>();
2876+ addRenderer<WaveformRenderBeat>();
2877+
2878+ setAttribute(Qt::WA_NoSystemBackground);
2879+ setAttribute(Qt::WA_OpaquePaintEvent);
2880+
2881+ m_initSuccess = init();
2882+}
2883+
2884+HSVWaveformWidget::~HSVWaveformWidget() {
2885+}
2886+
2887+void HSVWaveformWidget::castToQWidget() {
2888+ m_widget = static_cast<QWidget*>(this);
2889+}
2890+
2891+void HSVWaveformWidget::paintEvent( QPaintEvent* event) {
2892+ QPainter painter(this);
2893+ draw(&painter,event);
2894+}
2895
2896=== removed file 'mixxx/src/waveform/widgets/hsvwaveformwidget.cpp'
2897--- mixxx/src/waveform/widgets/hsvwaveformwidget.cpp 2013-01-04 20:29:33 +0000
2898+++ mixxx/src/waveform/widgets/hsvwaveformwidget.cpp 1970-01-01 00:00:00 +0000
2899@@ -1,41 +0,0 @@
2900-#include "hsvwaveformwidget.h"
2901-
2902-#include <QPainter>
2903-
2904-#include "waveform/renderers/waveformwidgetrenderer.h"
2905-#include "waveform/renderers/waveformrenderbackground.h"
2906-#include "waveform/renderers/waveformrendermark.h"
2907-#include "waveform/renderers/waveformrendermarkrange.h"
2908-#include "waveform/renderers/waveformrendererhsv.h"
2909-#include "waveform/renderers/waveformrendererpreroll.h"
2910-#include "waveform/renderers/waveformrendererendoftrack.h"
2911-#include "waveform/renderers/waveformrenderbeat.h"
2912-
2913-HSVWaveformWidget::HSVWaveformWidget( const char* group, QWidget* parent)
2914- : QWidget(parent),
2915- WaveformWidgetAbstract(group) {
2916- addRenderer<WaveformRenderBackground>();
2917- addRenderer<WaveformRendererEndOfTrack>();
2918- addRenderer<WaveformRendererPreroll>();
2919- addRenderer<WaveformRenderMarkRange>();
2920- addRenderer<WaveformRendererHSV>();
2921- addRenderer<WaveformRenderBeat>();
2922- addRenderer<WaveformRenderMark>();
2923-
2924- setAttribute(Qt::WA_NoSystemBackground);
2925- setAttribute(Qt::WA_OpaquePaintEvent);
2926-
2927- m_initSuccess = init();
2928-}
2929-
2930-HSVWaveformWidget::~HSVWaveformWidget() {
2931-}
2932-
2933-void HSVWaveformWidget::castToQWidget() {
2934- m_widget = static_cast<QWidget*>(this);
2935-}
2936-
2937-void HSVWaveformWidget::paintEvent( QPaintEvent* event) {
2938- QPainter painter(this);
2939- draw(&painter,event);
2940-}
2941
2942=== added file 'mixxx/src/waveform/widgets/hsvwaveformwidget.h'
2943--- mixxx/src/waveform/widgets/hsvwaveformwidget.h 1970-01-01 00:00:00 +0000
2944+++ mixxx/src/waveform/widgets/hsvwaveformwidget.h 2013-05-01 22:08:27 +0000
2945@@ -0,0 +1,29 @@
2946+#ifndef HSVWAVEFORMWIDGET_H
2947+#define HSVWAVEFORMWIDGET_H
2948+
2949+#include <QWidget>
2950+
2951+#include "waveformwidgetabstract.h"
2952+
2953+class HSVWaveformWidget : public QWidget, public WaveformWidgetAbstract {
2954+ Q_OBJECT
2955+ public:
2956+ virtual ~HSVWaveformWidget();
2957+
2958+ virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::HSVWaveform; }
2959+
2960+ static inline QString getWaveformWidgetName() { return tr("HSV"); }
2961+ static inline bool useOpenGl() { return false; }
2962+ static inline bool useOpenGLShaders() { return false; }
2963+ static inline bool developerOnly() { return false; }
2964+
2965+ protected:
2966+ virtual void castToQWidget();
2967+ virtual void paintEvent(QPaintEvent* event);
2968+
2969+ private:
2970+ HSVWaveformWidget(const char* group, QWidget* parent);
2971+ friend class WaveformWidgetFactory;
2972+};
2973+
2974+#endif // HSVWAVEFORMWIDGET_H
2975
2976=== removed file 'mixxx/src/waveform/widgets/hsvwaveformwidget.h'
2977--- mixxx/src/waveform/widgets/hsvwaveformwidget.h 2012-12-14 01:26:04 +0000
2978+++ mixxx/src/waveform/widgets/hsvwaveformwidget.h 1970-01-01 00:00:00 +0000
2979@@ -1,29 +0,0 @@
2980-#ifndef HSVWAVEFORMWIDGET_H
2981-#define HSVWAVEFORMWIDGET_H
2982-
2983-#include <QWidget>
2984-
2985-#include "waveformwidgetabstract.h"
2986-
2987-class HSVWaveformWidget : public QWidget, public WaveformWidgetAbstract {
2988- Q_OBJECT
2989- public:
2990- virtual ~HSVWaveformWidget();
2991-
2992- virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::HSVWaveform;}
2993-
2994- static inline QString getWaveformWidgetName() { return tr("HSV");}
2995- static inline bool useOpenGl() { return false;}
2996- static inline bool useOpenGLShaders() { return false;}
2997-
2998- protected:
2999- virtual void castToQWidget();
3000- virtual void paintEvent(QPaintEvent* event);
3001-
3002- private:
3003- HSVWaveformWidget() {}
3004- HSVWaveformWidget(const char* group, QWidget* parent);
3005- friend class WaveformWidgetFactory;
3006-};
3007-
3008-#endif // HSVWAVEFORMWIDGET_H
3009
3010=== modified file 'mixxx/src/waveform/widgets/qtsimplewaveformwidget.cpp'
3011--- mixxx/src/waveform/widgets/qtsimplewaveformwidget.cpp 2013-01-31 19:48:57 +0000
3012+++ mixxx/src/waveform/widgets/qtsimplewaveformwidget.cpp 2013-05-01 22:08:27 +0000
3013@@ -13,6 +13,8 @@
3014 #include "waveform/renderers/waveformrendererendoftrack.h"
3015 #include "waveform/renderers/waveformrenderbeat.h"
3016
3017+#include "util/performancetimer.h"
3018+
3019 QtSimpleWaveformWidget::QtSimpleWaveformWidget( const char* group, QWidget* parent)
3020 : QGLWidget(parent, SharedGLContext::getWidget()),
3021 WaveformWidgetAbstract(group) {
3022@@ -49,11 +51,24 @@
3023 }
3024
3025 void QtSimpleWaveformWidget::paintEvent(QPaintEvent* event) {
3026- if (QGLContext::currentContext() != context()) {
3027- makeCurrent();
3028- }
3029+ Q_UNUSED(event);
3030+}
3031+
3032+int QtSimpleWaveformWidget::render() {
3033+ PerformanceTimer timer;
3034+ int t1;
3035+ //int t2, t3;
3036+ timer.start();
3037+ // QPainter makes QGLContext::currentContext() == context()
3038+ // this may delayed until previous buffer swap finished
3039 QPainter painter(this);
3040- draw(&painter, event);
3041+ t1 = timer.restart();
3042+ draw(&painter, NULL);
3043+ //t2 = timer.restart();
3044+ //glFinish();
3045+ //t3 = timer.restart();
3046+ //qDebug() << "GLVSyncTestWidget "<< t1 << t2 << t3;
3047+ return t1/1000; // return timer for painter setup
3048 }
3049
3050 void QtSimpleWaveformWidget::postRender() {
3051
3052=== modified file 'mixxx/src/waveform/widgets/qtsimplewaveformwidget.h'
3053--- mixxx/src/waveform/widgets/qtsimplewaveformwidget.h 2012-09-19 21:04:53 +0000
3054+++ mixxx/src/waveform/widgets/qtsimplewaveformwidget.h 2013-05-01 22:08:27 +0000
3055@@ -12,19 +12,20 @@
3056 virtual ~QtSimpleWaveformWidget();
3057
3058
3059- virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::GLSimpleWaveform;}
3060+ virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::GLSimpleWaveform; }
3061
3062- static inline QString getWaveformWidgetName() { return tr("Simple") + " - Qt";}
3063- static inline bool useOpenGl() { return true;}
3064- static inline bool useOpenGLShaders() { return false;}
3065+ static inline QString getWaveformWidgetName() { return tr("Simple") + " - Qt"; }
3066+ static inline bool useOpenGl() { return true; }
3067+ static inline bool useOpenGLShaders() { return false; }
3068+ static inline bool developerOnly() { return false; }
3069
3070 protected:
3071 virtual void castToQWidget();
3072 virtual void paintEvent(QPaintEvent* event);
3073 virtual void postRender();
3074+ virtual int render();
3075
3076 private:
3077- QtSimpleWaveformWidget() {}
3078 friend class WaveformWidgetFactory;
3079 };
3080
3081
3082=== modified file 'mixxx/src/waveform/widgets/qtwaveformwidget.cpp'
3083--- mixxx/src/waveform/widgets/qtwaveformwidget.cpp 2013-01-04 20:29:33 +0000
3084+++ mixxx/src/waveform/widgets/qtwaveformwidget.cpp 2013-05-01 22:08:27 +0000
3085@@ -14,6 +14,8 @@
3086 #include "waveform/renderers/waveformrenderbeat.h"
3087 #include "sharedglcontext.h"
3088
3089+#include "util/performancetimer.h"
3090+
3091 QtWaveformWidget::QtWaveformWidget( const char* group, QWidget* parent)
3092 : QGLWidget(parent, SharedGLContext::getWidget()),
3093 WaveformWidgetAbstract(group) {
3094@@ -47,11 +49,24 @@
3095 }
3096
3097 void QtWaveformWidget::paintEvent( QPaintEvent* event) {
3098- if (QGLContext::currentContext() != context()) {
3099- makeCurrent();
3100- }
3101+ Q_UNUSED(event);
3102+}
3103+
3104+int QtWaveformWidget::render() {
3105+ PerformanceTimer timer;
3106+ int t1;
3107+ //int t2, t3;
3108+ timer.start();
3109+ // QPainter makes QGLContext::currentContext() == context()
3110+ // this may delayed until previous buffer swap finished
3111 QPainter painter(this);
3112- draw(&painter, event);
3113+ t1 = timer.restart();
3114+ draw(&painter, NULL);
3115+ //t2 = timer.restart();
3116+ //glFinish();
3117+ //t3 = timer.restart();
3118+ //qDebug() << "GLVSyncTestWidget "<< t1 << t2 << t3;
3119+ return t1/1000; // return timer for painter setup
3120 }
3121
3122 void QtWaveformWidget::postRender() {
3123
3124=== modified file 'mixxx/src/waveform/widgets/qtwaveformwidget.h'
3125--- mixxx/src/waveform/widgets/qtwaveformwidget.h 2012-09-19 21:39:13 +0000
3126+++ mixxx/src/waveform/widgets/qtwaveformwidget.h 2013-05-01 22:08:27 +0000
3127@@ -11,19 +11,20 @@
3128 QtWaveformWidget(const char* group, QWidget* parent);
3129 virtual ~QtWaveformWidget();
3130
3131- virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::QtWaveform;}
3132+ virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::QtWaveform; }
3133
3134- static inline QString getWaveformWidgetName() { return tr("Filtered") + " - Qt";}
3135- static inline bool useOpenGl() { return true;}
3136- static inline bool useOpenGLShaders() { return false;}
3137+ static inline QString getWaveformWidgetName() { return tr("Filtered") + " - Qt"; }
3138+ static inline bool useOpenGl() { return true; }
3139+ static inline bool useOpenGLShaders() { return false; }
3140+ static inline bool developerOnly() { return false; }
3141
3142 protected:
3143 virtual void castToQWidget();
3144 virtual void paintEvent(QPaintEvent* event);
3145 virtual void postRender();
3146+ virtual int render();
3147
3148 private:
3149- QtWaveformWidget() {}
3150 friend class WaveformWidgetFactory;
3151 };
3152
3153
3154=== modified file 'mixxx/src/waveform/widgets/softwarewaveformwidget.h'
3155--- mixxx/src/waveform/widgets/softwarewaveformwidget.h 2012-11-04 20:33:22 +0000
3156+++ mixxx/src/waveform/widgets/softwarewaveformwidget.h 2013-05-01 22:08:27 +0000
3157@@ -10,18 +10,18 @@
3158 public:
3159 virtual ~SoftwareWaveformWidget();
3160
3161- virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::SoftwareWaveform;}
3162+ virtual WaveformWidgetType::Type getType() const { return WaveformWidgetType::SoftwareWaveform; }
3163
3164- static inline QString getWaveformWidgetName() { return tr("Filtered") + " - " + tr("Software");}
3165- static inline bool useOpenGl() { return false;}
3166- static inline bool useOpenGLShaders() { return false;}
3167+ static inline QString getWaveformWidgetName() { return tr("Filtered") + " - " + tr("Software"); }
3168+ static inline bool useOpenGl() { return false; }
3169+ static inline bool useOpenGLShaders() { return false; }
3170+ static inline bool developerOnly() { return false; }
3171
3172 protected:
3173 virtual void castToQWidget();
3174 virtual void paintEvent(QPaintEvent* event);
3175
3176 private:
3177- SoftwareWaveformWidget() {}
3178 SoftwareWaveformWidget(const char* group, QWidget* parent);
3179 friend class WaveformWidgetFactory;
3180 };
3181
3182=== modified file 'mixxx/src/waveform/widgets/waveformwidgetabstract.cpp'
3183--- mixxx/src/waveform/widgets/waveformwidgetabstract.cpp 2012-12-10 17:23:43 +0000
3184+++ mixxx/src/waveform/widgets/waveformwidgetabstract.cpp 2013-05-01 22:08:27 +0000
3185@@ -4,15 +4,10 @@
3186 #include <QtDebug>
3187 #include <QWidget>
3188
3189-// Default constructor is only use by the factory to evaluate dynamically
3190-// WaveformWidget
3191-WaveformWidgetAbstract::WaveformWidgetAbstract() :
3192- WaveformWidgetRenderer() {
3193- m_widget = NULL;
3194-}
3195
3196-WaveformWidgetAbstract::WaveformWidgetAbstract( const char* group) :
3197- WaveformWidgetRenderer(group) {
3198+WaveformWidgetAbstract::WaveformWidgetAbstract( const char* group)
3199+ : WaveformWidgetRenderer(group),
3200+ m_initSuccess(false) {
3201 m_widget = NULL;
3202 }
3203
3204@@ -31,17 +26,15 @@
3205 }
3206 }
3207
3208-void WaveformWidgetAbstract::preRender() {
3209- WaveformWidgetRenderer::onPreRender();
3210+void WaveformWidgetAbstract::preRender(VSyncThread* vsyncThread) {
3211+ WaveformWidgetRenderer::onPreRender(vsyncThread);
3212 }
3213
3214-void WaveformWidgetAbstract::render() {
3215+int WaveformWidgetAbstract::render() {
3216 if (m_widget) {
3217- if (!m_widget->isVisible()) {
3218- m_widget->show();
3219- }
3220- m_widget->repaint();
3221+ m_widget->repaint(); // Repaints the widget directly by calling paintEvent()
3222 }
3223+ return 0; // Time for Painter setup, unknown in this case
3224 }
3225
3226 void WaveformWidgetAbstract::resize( int width, int height) {
3227
3228=== modified file 'mixxx/src/waveform/widgets/waveformwidgetabstract.h'
3229--- mixxx/src/waveform/widgets/waveformwidgetabstract.h 2012-09-19 21:04:53 +0000
3230+++ mixxx/src/waveform/widgets/waveformwidgetabstract.h 2013-05-01 22:08:27 +0000
3231@@ -8,6 +8,8 @@
3232 #include "waveformwidgettype.h"
3233 #include "trackinfoobject.h"
3234
3235+class VSyncThread;
3236+
3237 // NOTE(vRince) This class represent objects the waveformwidgetfactory can
3238 // holds, IMPORTANT all WaveformWidgetAbstract MUST inherist QWidget too !! we
3239 // can't do it here because QWidget and QGLWidget are both QWidgets so they
3240@@ -27,9 +29,9 @@
3241 void hold();
3242 void release();
3243
3244- virtual void preRender();
3245- virtual void render();
3246- virtual void postRender() {}
3247+ virtual void preRender(VSyncThread* vsyncThread);
3248+ virtual int render();
3249+ virtual void postRender() {};
3250
3251 virtual void resize( int width, int height);
3252
3253@@ -37,7 +39,6 @@
3254 QWidget* m_widget;
3255 bool m_initSuccess;
3256
3257- WaveformWidgetAbstract();
3258 //this is the factory resposability to trigger QWidget casting after constructor
3259 virtual void castToQWidget() = 0;
3260
3261
3262=== modified file 'mixxx/src/waveform/widgets/waveformwidgettype.h'
3263--- mixxx/src/waveform/widgets/waveformwidgettype.h 2012-12-13 22:46:16 +0000
3264+++ mixxx/src/waveform/widgets/waveformwidgettype.h 2013-05-01 22:08:27 +0000
3265@@ -6,13 +6,14 @@
3266 enum Type {
3267 EmptyWaveform = 0,
3268 SoftwareSimpleWaveform, //TODO
3269- SoftwareWaveform, //TODO
3270- QtSimpleWaveform, //TODO
3271+ SoftwareWaveform,
3272+ QtSimpleWaveform,
3273 QtWaveform,
3274 GLSimpleWaveform,
3275 GLWaveform,
3276 GLSLWaveform,
3277 HSVWaveform,
3278+ GLVSyncTest,
3279 Count_WaveformwidgetType // Also used as invalid value
3280 };
3281 };
3282
3283=== modified file 'mixxx/src/widget/wspinny.cpp'
3284--- mixxx/src/widget/wspinny.cpp 2013-04-05 23:13:45 +0000
3285+++ mixxx/src/widget/wspinny.cpp 2013-05-01 22:08:27 +0000
3286@@ -7,6 +7,7 @@
3287 #include "controlobject.h"
3288 #include "controlobjectthreadmain.h"
3289 #include "sharedglcontext.h"
3290+#include "visualplayposition.h"
3291 #include "wspinny.h"
3292
3293 WSpinny::WSpinny(QWidget* parent, VinylControlManager* pVCMan)
3294@@ -16,7 +17,6 @@
3295 m_pGhostImage(NULL),
3296 m_pPlay(NULL),
3297 m_pPlayPos(NULL),
3298- m_pVisualPlayPos(NULL),
3299 m_pDuration(NULL),
3300 m_pTrackSamples(NULL),
3301 m_pScratch(NULL),
3302@@ -50,7 +50,7 @@
3303
3304 WSpinny::~WSpinny() {
3305 // No need to delete anything if m_group is empty because setup() was not called.
3306- if (!m_group.isEmpty()) {
3307+ if (!m_group.isEmpty()) {
3308 WImageStore::deleteImage(m_pBgImage);
3309 WImageStore::deleteImage(m_pFgImage);
3310 WImageStore::deleteImage(m_pGhostImage);
3311@@ -96,8 +96,8 @@
3312 ConfigKey(group, "play")));
3313 m_pPlayPos = new ControlObjectThreadMain(ControlObject::getControl(
3314 ConfigKey(group, "playposition")));
3315- m_pVisualPlayPos = new ControlObjectThreadMain(ControlObject::getControl(
3316- ConfigKey(group, "visual_playposition")));
3317+ m_pVisualPlayPos = VisualPlayPosition::getVisualPlayPosition(group);
3318+
3319 m_pDuration = new ControlObjectThreadMain(ControlObject::getControl(
3320 ConfigKey(group, "duration")));
3321 m_pTrackSamples = new ControlObjectThreadMain(ControlObject::getControl(
3322@@ -115,8 +115,6 @@
3323
3324 m_pSlipEnabled = new ControlObjectThreadMain(ControlObject::getControl(
3325 ConfigKey(group, "slip_enabled")));
3326- m_pSlipPosition = new ControlObjectThreadMain(ControlObject::getControl(
3327- ConfigKey(group, "slip_playposition")));
3328
3329 #ifdef __VINYLCONTROL__
3330 m_pVinylControlSpeedType = new ControlObjectThreadMain(ControlObject::getControl(
3331@@ -211,8 +209,9 @@
3332 p.save();
3333 }
3334
3335- double playPosition = m_pVisualPlayPos->get();
3336- double slipPosition = m_pSlipPosition->get();
3337+ double playPosition = -1;
3338+ double slipPosition = -1;
3339+ m_pVisualPlayPos->getPlaySlipAt(0, &playPosition, &slipPosition);
3340
3341 if (playPosition != m_dAngleLastPlaypos) {
3342 m_fAngle = calculateAngle(playPosition);
3343
3344=== modified file 'mixxx/src/widget/wspinny.h'
3345--- mixxx/src/widget/wspinny.h 2013-03-23 12:47:24 +0000
3346+++ mixxx/src/widget/wspinny.h 2013-05-01 22:08:27 +0000
3347@@ -11,6 +11,7 @@
3348 #endif
3349
3350 class ControlObjectThreadMain;
3351+class VisualPlayPosition;
3352
3353 class WSpinny : public QGLWidget {
3354 Q_OBJECT
3355@@ -48,7 +49,7 @@
3356 QImage* m_pGhostImage;
3357 ControlObjectThreadMain* m_pPlay;
3358 ControlObjectThreadMain* m_pPlayPos;
3359- ControlObjectThreadMain* m_pVisualPlayPos;
3360+ VisualPlayPosition* m_pVisualPlayPos;
3361 ControlObjectThreadMain* m_pDuration;
3362 ControlObjectThreadMain* m_pTrackSamples;
3363 ControlObjectThreadMain* m_pTrackSampleRate;
3364@@ -60,7 +61,6 @@
3365 ControlObjectThreadMain* m_pVinylControlEnabled;
3366 ControlObjectThreadMain* m_pSignalEnabled;
3367 ControlObjectThreadMain* m_pSlipEnabled;
3368- ControlObjectThreadMain* m_pSlipPosition;
3369
3370 #ifdef __VINYLCONTROL__
3371 VinylControlManager* m_pVCManager;

Subscribers

People subscribed via source and target branches