Merge lp:~mixxxdevelopers/mixxx/waveform-dejerk into lp:~mixxxdevelopers/mixxx/trunk
- waveform-dejerk
- Merge into trunk
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 | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mixxx Development Team | Pending | ||
Review via email: mp+156977@code.launchpad.net |
Commit message
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 VisualPlayPosit
The Play position for the waveform is adjusted for the actual display time in
VisualPlayPosit
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.
- 3344. By Daniel Schürmann
-
merged from lp:mixxx
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
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; |
FYI branch needs the diff from https:/ /bazaar. launchpad. net/~mixxxdevel opers/mixxx/ release- 1.11.x/ revision/ 3836 in order to compile on OSX. Going to test branch on MacBookPro8,1 and iMac13,1