Merge lp:~ywwg/mixxx/features_xwax2 into lp:~mixxxdevelopers/mixxx/trunk

Proposed by Owen Williams on 2011-07-30
Status: Superseded
Proposed branch: lp:~ywwg/mixxx/features_xwax2
Merge into: lp:~mixxxdevelopers/mixxx/trunk
Diff against target: 1496 lines (+492/-161) (has conflicts)
28 files modified
mixxx/lib/xwax/timecoder.c (+1/-1)
mixxx/lib/xwax/timecoder_win32.cpp (+1/-1)
mixxx/src/dlgprefnovinyldlg.ui (+67/-0)
mixxx/src/dlgprefvinyl.cpp (+3/-0)
mixxx/src/dlgprefvinyldlg.ui (+7/-0)
mixxx/src/engine/enginebuffer.cpp (+3/-0)
mixxx/src/engine/enginebufferscalelinear.cpp (+0/-10)
mixxx/src/engine/enginedeck.cpp (+1/-2)
mixxx/src/engine/enginevinylsoundemu.cpp (+29/-25)
mixxx/src/engine/enginevinylsoundemu.h (+1/-1)
mixxx/src/engine/vinylcontrolcontrol.cpp (+6/-0)
mixxx/src/engine/vinylcontrolcontrol.h (+2/-0)
mixxx/src/mixxx.cpp (+9/-35)
mixxx/src/skin/legacyskinparser.cpp (+4/-2)
mixxx/src/skin/legacyskinparser.h (+3/-1)
mixxx/src/skin/skinloader.cpp (+4/-2)
mixxx/src/skin/skinloader.h (+2/-1)
mixxx/src/soundmanager.cpp (+1/-0)
mixxx/src/vinylcontrol/vinylcontrol.cpp (+15/-2)
mixxx/src/vinylcontrol/vinylcontrol.h (+6/-1)
mixxx/src/vinylcontrol/vinylcontrolmanager.cpp (+2/-6)
mixxx/src/vinylcontrol/vinylcontrolsignalwidget.cpp (+1/-1)
mixxx/src/vinylcontrol/vinylcontrolxwax.cpp (+103/-57)
mixxx/src/vinylcontrol/vinylcontrolxwax.h (+1/-0)
mixxx/src/waveform/waveformrenderer.cpp (+24/-1)
mixxx/src/waveform/waveformrenderer.h (+2/-1)
mixxx/src/widget/wspinny.cpp (+169/-10)
mixxx/src/widget/wspinny.h (+25/-1)
Text conflict in mixxx/src/dlgprefnovinyldlg.ui
To merge this branch: bzr merge lp:~ywwg/mixxx/features_xwax2
Reviewer Review Type Date Requested Status
RJ Skerry-Ryan 2011-07-30 Pending
Review via email: mp+69904@code.launchpad.net

Description of the change

I've continued working in features_xwax2 to make some fixes and updates to the vinyl control code. It would be nice if some of these fixes could go into trunk, other new features can probably wait if it breaks freeze too badly.

New Features:
* Show signal quality inside WSpinny
* More pleasant waveform stretching

Fixes:
* fix vinylsoundemu and take equivalent code out of EBSL
* when loading a track, update track duration with correct value
* keep vinyl control enabled when changing vinyl control preferences
* Absolute mode fixes (better for scratching)

To post a comment you must log in.
Bill Good (bkgood) wrote :
Download full text (59.9 KiB)

Changes in trunk won't go out until after 1.10, should this be retargeted at
LP:mixxx/1.10?
Bill

On Jul 30, 2011 3:21 PM, "Owen Williams" <email address hidden> wrote:
>
> Owen Williams has proposed merging lp:~ywwg/mixxx/features_xwax2 into
lp:mixxx.
>
> Requested reviews:
> RJ Ryan (rryan)
> Related bugs:
> Bug #528113 in Mixxx: "Vinyl control signal quality doesn't refresh"
> https://bugs.launchpad.net/mixxx/+bug/528113
> Bug #624925 in Mixxx: "Mixxx should switch to relative mode if looping is
enabled in absolute mode"
> https://bugs.launchpad.net/mixxx/+bug/624925
> Bug #624931 in Mixxx: "Scale BPM display does not work for vinyl control
in Mixxx 1.8 and below"
> https://bugs.launchpad.net/mixxx/+bug/624931
> Bug #669289 in Mixxx: "Enable needle cueing in relative mode"
> https://bugs.launchpad.net/mixxx/+bug/669289
> Bug #672758 in Mixxx: "Support 45 rpm vinyl mode"
> https://bugs.launchpad.net/mixxx/+bug/672758
>
> For more details, see:
> https://code.launchpad.net/~ywwg/mixxx/features_xwax2/+merge/69904
>
> I've continued working in features_xwax2 to make some fixes and updates to
the vinyl control code. It would be nice if some of these fixes could go
into trunk, other new features can probably wait if it breaks freeze too
badly.
>
> New Features:
> * Show signal quality inside WSpinny
> * More pleasant waveform stretching
>
> Fixes:
> * fix vinylsoundemu and take equivalent code out of EBSL
> * when loading a track, update track duration with correct value
> * keep vinyl control enabled when changing vinyl control preferences
> * Absolute mode fixes (better for scratching)
> --
> https://code.launchpad.net/~ywwg/mixxx/features_xwax2/+merge/69904
> Your team Mixxx Development Team is subscribed to branch lp:mixxx.
>
> === modified file 'mixxx/lib/xwax/timecoder.c'
> --- mixxx/lib/xwax/timecoder.c 2011-05-25 19:52:14 +0000
> +++ mixxx/lib/xwax/timecoder.c 2011-07-30 20:21:03 +0000
> @@ -519,7 +519,7 @@
>
> if (r >= 0) {
> //normalize position to milliseconds, not timecode steps --
Owen
> - r = r * 1000 / (tc->def->resolution * tc->speed);
> + r = (float)r * (1000.0 / (tc->def->resolution *
tc->speed));
> if (when)
> *when = tc->timecode_ticker * tc->dt;
> return r;
>
> === modified file 'mixxx/lib/xwax/timecoder_win32.cpp'
> --- mixxx/lib/xwax/timecoder_win32.cpp 2011-05-25 19:52:14 +0000
> +++ mixxx/lib/xwax/timecoder_win32.cpp 2011-07-30 20:21:03 +0000
> @@ -521,7 +521,7 @@
>
> if (r >= 0) {
> //normalize position to milliseconds, not timecode steps --
Owen
> - r = r * 1000 / (tc->def->resolution * tc->speed);
> + r = (float)r * (1000.0 / (tc->def->resolution *
tc->speed));
> if (when)
> *when = tc->timecode_ticker * tc->dt;
> return r;
>
> === modified file 'mixxx/src/dlgprefnovinyldlg.ui'
> --- mixxx/src/dlgprefnovinyldlg.ui 2011-05-26 10:22:03 +0000
> +++ mixxx/src/dlgprefnovinyldlg.ui 2011-07-30 20:21:03 +0000
> @@ -9,8 +9,13 @@
> <rect>
> <x>0</x>
> <y>0</y>
> +<<<<<<< TREE
> <width>461</width>
> <height...

Owen Williams (ywwg) wrote :

Right, 1.10. I've resubmitted the proposal with my intended target

RJ Skerry-Ryan (rryan) wrote :

Have the two branches diverged yet? Anyway i'll take a look. thanks owen!

On Sun, Jul 31, 2011 at 8:15 AM, Owen Williams <email address hidden> wrote:

> Right, 1.10. I've resubmitted the proposal with my intended target
> --
> https://code.launchpad.net/~ywwg/mixxx/features_xwax2/+merge/69904
> You are requested to review the proposed merge of
> lp:~ywwg/mixxx/features_xwax2 into lp:mixxx.
>

lp:~ywwg/mixxx/features_xwax2 updated on 2012-04-02
2664. By Owen Williams on 2011-07-31

Merge from lp:mixxx

2665. By Owen Williams on 2011-09-16

Calculate fabs value once, not three times

2666. By Owen Williams on 2011-09-17

Replace explicit number with #defined value

2667. By Owen Williams on 2011-09-17

Optimizing vinyl sound emu:
* precompute random values for dithering
* don't repeatedly calculate absolute value

2668. By Owen Williams on 2011-09-17

Also randomize position in noise buffer so right and left aren't aligned

2669. By Owen Williams on 2011-09-17

Always record pitch for steadypitch, not just when we have position

2670. By Owen Williams on 2011-09-17

Retweak pitch smoothing tweak. Make sure spurious values aren't in the ringbuffer

2671. By Owen Williams on 2011-09-25

Don't use static variables

2672. By Owen Williams on 2011-09-26

Merge from lp:mixxx

2673. By Owen Williams on 2011-09-28

include genre in search results

2674. By Owen Williams on 2011-09-28

merge from lp:mixxx

2675. By Owen Williams on 2011-09-30

Abstractify vinyl proxies more

2676. By Owen Williams on 2011-10-01

Don't change metadata-reported duration

2677. By Owen Williams on 2011-10-01

merge from lp:mixxx

2678. By Owen Williams on 2011-10-03

Merge with lp:mixxx

2679. By Owen Williams on 2011-10-04

merge from lp:mixxx

2680. By Owen Williams on 2011-10-04

merged into trunk

2681. By Owen Williams on 2012-04-02

merge from lp:mixxx

2682. By Owen Williams on 2012-04-02

If rate is exactly 1.0, don't scale audio at all

2683. By Owen Williams on 2012-04-02

Since my wave writer code is so useful, make it something I can #define to enable

2684. By Owen Williams on 2012-04-02

Create vinylcontrol_scratching CO that is 1 when pitch is changing rapidly and 0 when not.
Use new vinylcontrol_scatching CO to trigger swap between keylock and linear scaling in engine.

2685. By Owen Williams on 2012-04-02

Vinyl Control bugfixes:
  * fix steady pitch detector to work in reverse and better detect loops
  * try not to enter track selection mode when scratching

2686. By Owen Williams on 2012-04-02

typo

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'mixxx/lib/xwax/timecoder.c'
2--- mixxx/lib/xwax/timecoder.c 2011-05-25 19:52:14 +0000
3+++ mixxx/lib/xwax/timecoder.c 2011-07-30 20:21:03 +0000
4@@ -519,7 +519,7 @@
5
6 if (r >= 0) {
7 //normalize position to milliseconds, not timecode steps -- Owen
8- r = r * 1000 / (tc->def->resolution * tc->speed);
9+ r = (float)r * (1000.0 / (tc->def->resolution * tc->speed));
10 if (when)
11 *when = tc->timecode_ticker * tc->dt;
12 return r;
13
14=== modified file 'mixxx/lib/xwax/timecoder_win32.cpp'
15--- mixxx/lib/xwax/timecoder_win32.cpp 2011-05-25 19:52:14 +0000
16+++ mixxx/lib/xwax/timecoder_win32.cpp 2011-07-30 20:21:03 +0000
17@@ -521,7 +521,7 @@
18
19 if (r >= 0) {
20 //normalize position to milliseconds, not timecode steps -- Owen
21- r = r * 1000 / (tc->def->resolution * tc->speed);
22+ r = (float)r * (1000.0 / (tc->def->resolution * tc->speed));
23 if (when)
24 *when = tc->timecode_ticker * tc->dt;
25 return r;
26
27=== modified file 'mixxx/src/dlgprefnovinyldlg.ui'
28--- mixxx/src/dlgprefnovinyldlg.ui 2011-05-26 10:22:03 +0000
29+++ mixxx/src/dlgprefnovinyldlg.ui 2011-07-30 20:21:03 +0000
30@@ -9,8 +9,13 @@
31 <rect>
32 <x>0</x>
33 <y>0</y>
34+<<<<<<< TREE
35 <width>461</width>
36 <height>527</height>
37+=======
38+ <width>504</width>
39+ <height>501</height>
40+>>>>>>> MERGE-SOURCE
41 </rect>
42 </property>
43 <property name="windowTitle">
44@@ -317,6 +322,13 @@
45 </property>
46 </spacer>
47 </item>
48+ <item row="3" column="0" colspan="3">
49+ <widget class="QCheckBox" name="SignalQualityEnable">
50+ <property name="text">
51+ <string>Show Signal Quality in Skin</string>
52+ </property>
53+ </widget>
54+ </item>
55 </layout>
56 </widget>
57 </item>
58@@ -406,9 +418,26 @@
59 </property>
60 </spacer>
61 </item>
62+ <item row="1" column="0">
63+ <widget class="QLabel" name="label">
64+ <property name="enabled">
65+ <bool>false</bool>
66+ </property>
67+ <property name="toolTip">
68+ <string>http://www.xwax.co.uk</string>
69+ </property>
70+ <property name="text">
71+ <string>Powered by xwax</string>
72+ </property>
73+ <property name="alignment">
74+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
75+ </property>
76+ </widget>
77+ </item>
78 </layout>
79 </widget>
80 </item>
81+<<<<<<< TREE
82 <item row="6" column="0" colspan="2">
83 <widget class="QLabel" name="label_3">
84 <property name="text">
85@@ -458,6 +487,9 @@
86 </widget>
87 </item>
88 <item row="6" column="2" rowspan="2">
89+=======
90+ <item row="6" column="2">
91+>>>>>>> MERGE-SOURCE
92 <spacer name="verticalSpacer">
93 <property name="orientation">
94 <enum>Qt::Vertical</enum>
95@@ -470,6 +502,41 @@
96 </property>
97 </spacer>
98 </item>
99+<<<<<<< TREE
100+=======
101+ <item row="5" column="2">
102+ <widget class="QPushButton" name="applyButton">
103+ <property name="enabled">
104+ <bool>false</bool>
105+ </property>
106+ <property name="sizePolicy">
107+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
108+ <horstretch>0</horstretch>
109+ <verstretch>0</verstretch>
110+ </sizepolicy>
111+ </property>
112+ <property name="sizeHint" stdset="0">
113+ <size>
114+ <width>85</width>
115+ <height>27</height>
116+ </size>
117+ </property>
118+ <property name="text">
119+ <string>Apply</string>
120+ </property>
121+ </widget>
122+ </item>
123+ <item row="5" column="0" colspan="2">
124+ <widget class="QLabel" name="label_3">
125+ <property name="text">
126+ <string>&lt;b&gt;This version of Mixxx does not support vinyl control.&lt;/b&gt; &lt;br&gt; Please visit &lt;a href=&quot;http://mixxx.org&quot;&gt;Mixxx.org&lt;/a&gt; for more information.</string>
127+ </property>
128+ <property name="wordWrap">
129+ <bool>true</bool>
130+ </property>
131+ </widget>
132+ </item>
133+>>>>>>> MERGE-SOURCE
134 </layout>
135 </widget>
136 <layoutdefault spacing="6" margin="11"/>
137
138=== modified file 'mixxx/src/dlgprefvinyl.cpp'
139--- mixxx/src/dlgprefvinyl.cpp 2011-05-11 04:38:17 +0000
140+++ mixxx/src/dlgprefvinyl.cpp 2011-07-30 20:21:03 +0000
141@@ -137,6 +137,8 @@
142
143 // Honour the Needle Skip Prevention setting.
144 NeedleSkipEnable->setChecked( (bool)config->getValueString( ConfigKey("[VinylControl]", "needle_skip_prevention") ).toInt() );
145+
146+ SignalQualityEnable->setChecked((bool)config->getValueString(ConfigKey("[VinylControl]", "show_signal_quality") ).toInt() );
147
148 //set vinyl control gain
149 VinylGain->setValue( config->getValueString(ConfigKey("[VinylControl]","gain")).toInt());
150@@ -182,6 +184,7 @@
151 m_COMode.slotSet(iMode);
152 config->set(ConfigKey("[VinylControl]","mode"), ConfigValue(iMode));
153 config->set(ConfigKey("[VinylControl]","needle_skip_prevention" ), ConfigValue( (int)(NeedleSkipEnable->isChecked( )) ) );
154+ config->set(ConfigKey("[VinylControl]","show_signal_quality" ), ConfigValue( (int)(SignalQualityEnable->isChecked( )) ) );
155
156 m_pVCManager->reloadConfig();
157 slotUpdate();
158
159=== modified file 'mixxx/src/dlgprefvinyldlg.ui'
160--- mixxx/src/dlgprefvinyldlg.ui 2011-05-26 10:22:03 +0000
161+++ mixxx/src/dlgprefvinyldlg.ui 2011-07-30 20:21:03 +0000
162@@ -308,6 +308,13 @@
163 </property>
164 </spacer>
165 </item>
166+ <item row="3" column="0" colspan="3">
167+ <widget class="QCheckBox" name="SignalQualityEnable">
168+ <property name="text">
169+ <string>Show Signal Quality in Skin</string>
170+ </property>
171+ </widget>
172+ </item>
173 </layout>
174 </widget>
175 </item>
176
177=== modified file 'mixxx/src/engine/enginebuffer.cpp'
178--- mixxx/src/engine/enginebuffer.cpp 2011-05-01 19:10:21 +0000
179+++ mixxx/src/engine/enginebuffer.cpp 2011-07-30 20:21:03 +0000
180@@ -336,6 +336,9 @@
181 m_pTrackSampleRate->set(iTrackSampleRate);
182 slotControlSeek(0.);
183
184+ //fix the duration
185+ pTrack->setDuration(iTrackNumSamples / (2 * iTrackSampleRate));
186+
187
188 // Let the engine know that a track is loaded now.
189 m_pTrackEndCOT->slotSet(0.0f); //XXX: Not sure if to use the COT or CO here
190
191=== modified file 'mixxx/src/engine/enginebufferscalelinear.cpp'
192--- mixxx/src/engine/enginebufferscalelinear.cpp 2011-04-16 20:51:48 +0000
193+++ mixxx/src/engine/enginebufferscalelinear.cpp 2011-07-30 20:21:03 +0000
194@@ -326,16 +326,6 @@
195 //at extremely low speeds, dampen the gain to hide pops and clicks
196 //this does cause odd-looking linear waveforms that go to zero and back
197
198- //although enginevinylsoundemu does this, it works much better here
199- //because the gain ramps as the rate does
200- if (fabs(rate_add) < 0.5) {
201- float dither = (float)(rand() % 32768) / 32768 - 0.5; // dither
202- //float dither = 0;
203- float gainfrac = fabs(rate_add) / 0.5;
204- buf[i] = gainfrac * (float)buf[i] + dither;
205- buf[i+1] = gainfrac * (float)buf[i+1] + dither;
206- }
207-
208 /*writer << QString("%1,%2,%3,%4\n").arg(buffer_count)
209 .arg(buffer[i])
210 .arg(prev_sample[0])
211
212=== modified file 'mixxx/src/engine/enginedeck.cpp'
213--- mixxx/src/engine/enginedeck.cpp 2011-04-15 22:19:45 +0000
214+++ mixxx/src/engine/enginedeck.cpp 2011-07-30 20:21:03 +0000
215@@ -54,8 +54,7 @@
216 // Process the raw audio
217 m_pBuffer->process(0, pOut, iBufferSize);
218 // Emulate vinyl sounds
219- // This causes popping, disable -Owen
220- //m_pVinylSoundEmu->process(pOut, pOut, iBufferSize);
221+ m_pVinylSoundEmu->process(pOut, pOut, iBufferSize);
222 // Apply pregain
223 m_pPregain->process(pOut, pOut, iBufferSize);
224 // Filter the channel with EQs
225
226=== modified file 'mixxx/src/engine/enginevinylsoundemu.cpp'
227--- mixxx/src/engine/enginevinylsoundemu.cpp 2010-09-17 04:15:33 +0000
228+++ mixxx/src/engine/enginevinylsoundemu.cpp 2011-07-30 20:21:03 +0000
229@@ -23,7 +23,7 @@
230
231 /** This class emulates the response of a vinyl record's audio to changes
232 * in speed. In practice, it quiets the audio during very slow playback.
233- * This also helps mask the aliasing due to interpolation that occurs at
234+ * Dithering also helps mask the aliasing due to interpolation that occurs at
235 * these slow speeds.
236 */
237
238@@ -31,7 +31,7 @@
239 {
240 m_pConfig = pConfig;
241 m_pRateEngine = ControlObject::getControl(ConfigKey(group, "rateEngine"));
242- m_fAbsSpeed = 0.0f;
243+ m_fSpeed = m_fOldSpeed = 0.0f;
244 m_fGainFactor = 1.0f;
245 }
246
247@@ -43,30 +43,34 @@
248 void EngineVinylSoundEmu::process(const CSAMPLE * pIn, const CSAMPLE * pOut, const int iBufferSize)
249 {
250 CSAMPLE * pOutput = (CSAMPLE *)pOut;
251- m_fAbsSpeed = fabs((float)m_pRateEngine->get());
252- //qDebug() << m_pRateEngine->get();
253+ m_fSpeed = (float)m_pRateEngine->get();
254+ float rateFrac = 2 * (m_fSpeed - m_fOldSpeed) / (float)iBufferSize;
255+ float curRate = m_fOldSpeed;
256
257 const float thresholdSpeed = 0.070f; //Scale volume if playback speed is below 7%.
258- if (m_fAbsSpeed < thresholdSpeed && m_fAbsSpeed > 0.0f) //Change the volume based on the playback speed.
259- {
260- //The numbers in this formula are important:
261- // - The "1 + ..." makes the minimum value of the parameter of log10
262- // be 1, which makes the gain 0.
263- // - The "* 9" makes the maximum value of the log10 become 10 (9 + 1 = 10)
264- // which gives a gain of 1
265- //m_fGainFactor = log10(1 + m_fAbsSpeed/0.50f * 9);
266- m_fGainFactor = m_fAbsSpeed/thresholdSpeed;
267- //qDebug() << m_fGainFactor << m_fAbsSpeed;
268- }
269- else if (m_fAbsSpeed == 0.0f)
270- m_fGainFactor = 0.0f; //Log blows up at 0 :)
271- else
272- {
273- m_fGainFactor = 1.0f;
274- }
275-
276- // Apply whatever gain we calculated. SampleUtil takes care of aliased
277- // buffers and gains of 1 or 0.
278- SampleUtil::copyWithGain(pOutput, pIn, m_fGainFactor, iBufferSize);
279+ const float ditherSpeed = 0.85f; //Dither if playback speed is below 85%.
280+
281+ //iterate over old rate to new rate to prevent audible pops
282+ for (int i=0; i<iBufferSize; i+=2)
283+ {
284+ float dither = 0;
285+ if (fabs(curRate) < ditherSpeed) {
286+ dither = (float)(rand() % 32768) / 32768 - 0.5;
287+ }
288+
289+ if (fabs(curRate) < thresholdSpeed) {
290+ float gainfrac = fabs(curRate) / thresholdSpeed;
291+ pOutput[i] = gainfrac * (float)pIn[i] + dither;
292+ pOutput[i+1] = gainfrac * (float)pIn[i+1] + dither;
293+ }
294+ else
295+ {
296+ pOutput[i] = pIn[i] + dither;
297+ pOutput[i+1] = pIn[i+1] + dither;
298+ }
299+
300+ curRate += rateFrac;
301+ }
302+ m_fOldSpeed = m_fSpeed;
303 }
304
305
306=== modified file 'mixxx/src/engine/enginevinylsoundemu.h'
307--- mixxx/src/engine/enginevinylsoundemu.h 2009-01-24 04:39:32 +0000
308+++ mixxx/src/engine/enginevinylsoundemu.h 2011-07-30 20:21:03 +0000
309@@ -28,7 +28,7 @@
310 private:
311 ConfigObject<ConfigValue> *m_pConfig;
312 ControlObject *m_pRateEngine;
313- float m_fAbsSpeed;
314+ float m_fSpeed, m_fOldSpeed;
315 float m_fGainFactor;
316 };
317
318
319=== modified file 'mixxx/src/engine/vinylcontrolcontrol.cpp'
320--- mixxx/src/engine/vinylcontrolcontrol.cpp 2011-05-11 04:38:17 +0000
321+++ mixxx/src/engine/vinylcontrolcontrol.cpp 2011-07-30 20:21:03 +0000
322@@ -27,12 +27,18 @@
323 m_pControlVinylEnabled = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_enabled"));
324 m_pControlVinylEnabled->set(0);
325 m_pControlVinylEnabled->setToggleButton(true);
326+ m_pControlVinylWantEnabled = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_wantenabled"));
327+ m_pControlVinylWantEnabled->set(0);
328+ m_pControlVinylWantEnabled->setToggleButton(true);
329 m_pControlVinylMode = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_mode"));
330 m_pControlVinylMode->setStates(3);
331 m_pControlVinylMode->setToggleButton(true);
332 m_pControlVinylCueing = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_cueing"));
333 m_pControlVinylCueing->setStates(3);
334 m_pControlVinylCueing->setToggleButton(true);
335+ m_pControlVinylSignalEnabled = new ControlPushButton(ConfigKey(pGroup, "vinylcontrol_signal_enabled"));
336+ m_pControlVinylSignalEnabled->set(1);
337+ m_pControlVinylSignalEnabled->setToggleButton(true);
338 }
339
340 VinylControlControl::~VinylControlControl() {
341
342=== modified file 'mixxx/src/engine/vinylcontrolcontrol.h'
343--- mixxx/src/engine/vinylcontrolcontrol.h 2011-05-11 04:38:17 +0000
344+++ mixxx/src/engine/vinylcontrolcontrol.h 2011-07-30 20:21:03 +0000
345@@ -25,7 +25,9 @@
346 ControlObject* m_pControlVinylStatus;
347 ControlPushButton* m_pControlVinylMode;
348 ControlPushButton* m_pControlVinylEnabled;
349+ ControlPushButton* m_pControlVinylWantEnabled;
350 ControlPushButton* m_pControlVinylCueing;
351+ ControlPushButton* m_pControlVinylSignalEnabled;
352 TrackPointer m_pCurrentTrack;
353 };
354
355
356=== modified file 'mixxx/src/mixxx.cpp'
357--- mixxx/src/mixxx.cpp 2011-05-06 09:45:12 +0000
358+++ mixxx/src/mixxx.cpp 2011-07-30 20:21:03 +0000
359@@ -481,7 +481,8 @@
360 if (!(m_pWidgetParent = m_pSkinLoader->loadDefaultSkin(m_pView,
361 m_pKeyboard,
362 m_pPlayerManager,
363- m_pLibrary))) {
364+ m_pLibrary,
365+ m_pVCManager))) {
366 qDebug() << "Could not load default skin.";
367 }
368
369@@ -875,9 +876,6 @@
370 // Either check or uncheck the vinyl control menu item depending on what
371 // it was saved as.
372 m_pOptionsVinylControl->setCheckable(true);
373- //make sure control is off on startup (this is redundant to vinylcontrolmanager.cpp)
374- m_pConfig->set(
375- ConfigKey("[VinylControl]", "enabled_ch1"), false);
376 m_pOptionsVinylControl->setChecked(false);
377 m_pOptionsVinylControl->setStatusTip(tr("Activate Vinyl Control"));
378 m_pOptionsVinylControl->setWhatsThis(
379@@ -891,8 +889,6 @@
380 SLOT(slotControlVinylControl(double)));
381
382 m_pOptionsVinylControl2->setCheckable(true);
383- m_pConfig->set(
384- ConfigKey("[VinylControl]", "enabled_ch2"), false);
385 m_pOptionsVinylControl2->setChecked(false);
386 m_pOptionsVinylControl2->setStatusTip(tr("Activate Vinyl Control"));
387 m_pOptionsVinylControl2->setWhatsThis(
388@@ -1162,15 +1158,9 @@
389 {
390 #ifdef __VINYLCONTROL__
391 if (m_pVCManager->vinylInputEnabled(1)) {
392- m_pConfig->set(
393- ConfigKey("[VinylControl]", "enabled_ch1"), ConfigValue((int)toggle));
394 m_pOptionsVinylControl->setChecked((bool)toggle);
395- if (toggle) {
396- ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_status"))->set(VINYL_STATUS_OK);
397- } else {
398- ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);
399- }
400 } else {
401+ m_pOptionsVinylControl->setChecked(false);
402 if (toggle) {
403 QMessageBox::warning(this, tr("Mixxx"),
404 tr("No input device(s) select.\nPlease select your soundcard(s) "
405@@ -1179,8 +1169,6 @@
406 QMessageBox::Ok);
407 m_pPrefDlg->show();
408 m_pPrefDlg->showSoundHardwarePage();
409- m_pOptionsVinylControl->setChecked(false);
410- m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch1"), ConfigValue(0));
411 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);
412 ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_enabled"))->set(0);
413 }
414@@ -1191,27 +1179,17 @@
415 void MixxxApp::slotCheckboxVinylControl(bool toggle)
416 {
417 #ifdef __VINYLCONTROL__
418- bool current = (bool)m_pConfig->getValueString(ConfigKey("[VinylControl]","enabled_ch1")).toInt();
419- if (current != toggle) {
420- ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_enabled"))->set((double)toggle);
421- }
422+ ControlObject::getControl(ConfigKey("[Channel1]", "vinylcontrol_enabled"))->set((double)toggle);
423 #endif
424 }
425
426 void MixxxApp::slotControlVinylControl2(double toggle)
427 {
428 #ifdef __VINYLCONTROL__
429- //we just need at least 1 input (deck 1) because of single deck mode
430 if (m_pVCManager->vinylInputEnabled(2)) {
431- m_pConfig->set(
432- ConfigKey("[VinylControl]", "enabled_ch2"), ConfigValue((int)toggle));
433- m_pOptionsVinylControl2->setChecked((bool)toggle);
434- if (toggle) {
435- ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_status"))->set(VINYL_STATUS_OK);
436- } else {
437- ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);
438- }
439+ m_pOptionsVinylControl2->setChecked((bool)toggle);
440 } else {
441+ m_pOptionsVinylControl2->setChecked(false);
442 if (toggle) {
443 QMessageBox::warning(this, tr("Mixxx"),
444 tr("No input device(s) select.\nPlease select your soundcard(s) "
445@@ -1220,8 +1198,6 @@
446 QMessageBox::Ok);
447 m_pPrefDlg->show();
448 m_pPrefDlg->showSoundHardwarePage();
449- m_pOptionsVinylControl2->setChecked(false);
450- m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch2"), ConfigValue(0));
451 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_status"))->set(VINYL_STATUS_DISABLED);
452 ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_enabled"))->set(0);
453 }
454@@ -1232,10 +1208,7 @@
455 void MixxxApp::slotCheckboxVinylControl2(bool toggle)
456 {
457 #ifdef __VINYLCONTROL__
458- bool current = (bool)m_pConfig->getValueString(ConfigKey("[VinylControl]","enabled_ch2")).toInt();
459- if (current != toggle) {
460- ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_enabled"))->set((double)toggle);
461- }
462+ ControlObject::getControl(ConfigKey("[Channel2]", "vinylcontrol_enabled"))->set((double)toggle);
463 #endif
464 }
465
466@@ -1428,7 +1401,8 @@
467 if (!(m_pWidgetParent = m_pSkinLoader->loadDefaultSkin(m_pView,
468 m_pKeyboard,
469 m_pPlayerManager,
470- m_pLibrary))) {
471+ m_pLibrary,
472+ m_pVCManager))) {
473 qDebug() << "Could not reload the skin.";
474 }
475
476
477=== modified file 'mixxx/src/skin/legacyskinparser.cpp'
478--- mixxx/src/skin/legacyskinparser.cpp 2011-05-05 21:29:33 +0000
479+++ mixxx/src/skin/legacyskinparser.cpp 2011-07-30 20:21:03 +0000
480@@ -58,11 +58,13 @@
481 LegacySkinParser::LegacySkinParser(ConfigObject<ConfigValue>* pConfig,
482 MixxxKeyboard* pKeyboard,
483 PlayerManager* pPlayerManager,
484- Library* pLibrary)
485+ Library* pLibrary,
486+ VinylControlManager* pVCMan)
487 : m_pConfig(pConfig),
488 m_pKeyboard(pKeyboard),
489 m_pPlayerManager(pPlayerManager),
490 m_pLibrary(pLibrary),
491+ m_pVCManager(pVCMan),
492 m_pParent(NULL) {
493
494 }
495@@ -611,7 +613,7 @@
496 QWidget* LegacySkinParser::parseSpinny(QDomElement node) {
497 QString channelStr = lookupNodeGroup(node);
498 const char* pSafeChannelStr = safeChannelString(channelStr);
499- WSpinny* p = new WSpinny(m_pParent);
500+ WSpinny* p = new WSpinny(m_pParent, m_pVCManager);
501 setupWidget(node, p);
502
503 connect(p, SIGNAL(trackDropped(QString, QString)),
504
505=== modified file 'mixxx/src/skin/legacyskinparser.h'
506--- mixxx/src/skin/legacyskinparser.h 2011-04-29 03:18:02 +0000
507+++ mixxx/src/skin/legacyskinparser.h 2011-07-30 20:21:03 +0000
508@@ -9,6 +9,7 @@
509
510 #include "configobject.h"
511 #include "skin/skinparser.h"
512+#include "vinylcontrol/vinylcontrolmanager.h"
513
514 class Library;
515 class MixxxKeyboard;
516@@ -20,7 +21,7 @@
517 public:
518 LegacySkinParser(ConfigObject<ConfigValue>* pConfig,
519 MixxxKeyboard* pKeyboard, PlayerManager* pPlayerManager,
520- Library* pLibrary);
521+ Library* pLibrary, VinylControlManager* pVCMan);
522 virtual ~LegacySkinParser();
523
524 virtual bool canParse(QString skinPath);
525@@ -73,6 +74,7 @@
526 MixxxKeyboard* m_pKeyboard;
527 PlayerManager* m_pPlayerManager;
528 Library* m_pLibrary;
529+ VinylControlManager* m_pVCManager;
530 QWidget *m_pParent;
531 static QList<const char*> s_channelStrs;
532 static QMutex s_safeStringMutex;
533
534=== modified file 'mixxx/src/skin/skinloader.cpp'
535--- mixxx/src/skin/skinloader.cpp 2011-01-07 22:31:50 +0000
536+++ mixxx/src/skin/skinloader.cpp 2011-07-30 20:21:03 +0000
537@@ -5,6 +5,7 @@
538 #include <QDir>
539 #include <QtDebug>
540
541+#include "vinylcontrol/vinylcontrolmanager.h"
542 #include "skin/skinloader.h"
543 #include "skin/legacyskinparser.h"
544
545@@ -52,10 +53,11 @@
546 QWidget* SkinLoader::loadDefaultSkin(QWidget* pParent,
547 MixxxKeyboard* pKeyboard,
548 PlayerManager* pPlayerManager,
549- Library* pLibrary) {
550+ Library* pLibrary,
551+ VinylControlManager* pVCMan) {
552 QString skinPath = getConfiguredSkinPath();
553
554- LegacySkinParser legacy(m_pConfig, pKeyboard, pPlayerManager, pLibrary);
555+ LegacySkinParser legacy(m_pConfig, pKeyboard, pPlayerManager, pLibrary, pVCMan);
556 qDebug() << "Legacy can parse:" << legacy.canParse(skinPath);
557 return legacy.parseSkin(skinPath, pParent);
558 }
559
560=== modified file 'mixxx/src/skin/skinloader.h'
561--- mixxx/src/skin/skinloader.h 2011-01-06 19:05:52 +0000
562+++ mixxx/src/skin/skinloader.h 2011-07-30 20:21:03 +0000
563@@ -17,7 +17,8 @@
564 QWidget* loadDefaultSkin(QWidget* pParent,
565 MixxxKeyboard* pKeyboard,
566 PlayerManager* pPlayerManager,
567- Library* pLibrary);
568+ Library* pLibrary,
569+ VinylControlManager* pVCMan);
570
571 QString getConfiguredSkinPath();
572
573
574=== modified file 'mixxx/src/soundmanager.cpp'
575--- mixxx/src/soundmanager.cpp 2011-07-19 18:12:33 +0000
576+++ mixxx/src/soundmanager.cpp 2011-07-30 20:21:03 +0000
577@@ -26,6 +26,7 @@
578 #include "sounddevice.h"
579 #include "sounddeviceportaudio.h"
580 #include "engine/enginemaster.h"
581+#include "engine/enginebuffer.h"
582 #include "controlobjectthreadmain.h"
583 #include "soundmanagerutil.h"
584 #include "controlobject.h"
585
586=== modified file 'mixxx/src/vinylcontrol/vinylcontrol.cpp'
587--- mixxx/src/vinylcontrol/vinylcontrol.cpp 2011-04-29 16:57:44 +0000
588+++ mixxx/src/vinylcontrol/vinylcontrol.cpp 2011-07-30 20:21:03 +0000
589@@ -11,6 +11,8 @@
590
591 // Get Control objects
592 playPos = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "playposition"))); //Range: -.14 to 1.14
593+ trackSamples = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "track_samples")));
594+ trackSampleRate = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "track_samplerate")));
595 vinylSeek = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_seek")));
596 controlScratch = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "scratch2")));
597 rateSlider = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "rate"))); //Range -1.0 to 1.0
598@@ -19,11 +21,13 @@
599 duration = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "duration")));
600 mode = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_mode")));
601 enabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_enabled")));
602+ wantenabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_wantenabled")));
603 cueing = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_cueing")));
604 rateRange = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "rateRange")));
605 vinylStatus = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_status")));
606 rateDir = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "rate_dir")));
607 loopEnabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "loop_enabled")));
608+ signalenabled = new ControlObjectThread(ControlObject::getControl(ConfigKey(group, "vinylcontrol_signal_enabled")));
609
610 dVinylPitch = 0.0f;
611 dVinylPosition = 0.0f;
612@@ -47,8 +51,8 @@
613 //Vinyl control mode
614 iVCMode = m_pConfig->getValueString(ConfigKey("[VinylControl]","mode")).toInt();
615
616- //Enabled or not
617- bIsEnabled = m_pConfig->getValueString(ConfigKey(group,"vinylcontrol_enabled")).toInt();
618+ //Enabled or not -- load from saved value in case vinyl control is restarting
619+ bIsEnabled = wantenabled->get();
620
621 //Gain
622 ControlObject::getControl(ConfigKey("[VinylControl]", "gain"))->set(
623@@ -59,7 +63,9 @@
624 {
625 bIsEnabled = enable;
626 if (m_pConfig)
627+ {
628 m_pConfig->set(ConfigKey(m_group,"vinylcontrol_enabled"), ConfigValue((int)enable));
629+ }
630
631 enabled->slotSet(enable);
632
633@@ -71,8 +77,15 @@
634
635 VinylControl::~VinylControl()
636 {
637+ bool wasEnabled = bIsEnabled;
638 enabled->slotSet(false);
639 vinylStatus->slotSet(VINYL_STATUS_DISABLED);
640+ if (wasEnabled)
641+ {
642+ //if vinyl control is just restarting, indicate that it should
643+ //be enabled
644+ wantenabled->slotSet(true);
645+ }
646 }
647
648 float VinylControl::getSpeed()
649
650=== modified file 'mixxx/src/vinylcontrol/vinylcontrol.h'
651--- mixxx/src/vinylcontrol/vinylcontrol.h 2011-05-11 04:38:17 +0000
652+++ mixxx/src/vinylcontrol/vinylcontrol.h 2011-07-30 20:21:03 +0000
653@@ -35,7 +35,7 @@
654
655 #define MIXXX_VC_DEFAULT_LEADINTIME 0
656
657-#define MIXXX_VINYL_SCOPE_SIZE 128
658+#define MIXXX_VINYL_SCOPE_SIZE 100
659
660 //TODO: Make this an EngineObject instead one day? (need to route all the input audio through the engine that way too...)
661
662@@ -62,6 +62,8 @@
663 QString m_group;
664 ControlObjectThread *playButton; //The ControlObject used to start/stop playback of the song.
665 ControlObjectThread *playPos; //The ControlObject used to read the playback position in the song.
666+ ControlObjectThread *trackSamples;
667+ ControlObjectThread *trackSampleRate;
668 ControlObjectThread *vinylSeek; //The ControlObject used to change the playback position in the song.
669 ControlObjectThread *controlScratch; //The ControlObject used to seek when the record is spinning fast.
670 ControlObjectThread *rateSlider; //The ControlObject used to change the speed/pitch of the song.
671@@ -69,11 +71,13 @@
672 ControlObjectThread *duration; //The ControlObject used to get the duration of the current song.
673 ControlObjectThread *mode; //The ControlObject used to get the vinyl control mode (absolute/relative/scratch)
674 ControlObjectThread *enabled; //The ControlObject used to get if the vinyl control is enabled or disabled.
675+ ControlObjectThread *wantenabled; //The ControlObject used to get if the vinyl control should try to enable itself
676 ControlObjectThread *cueing; //Should cueing mode be active?
677 ControlObjectThread *rateRange; //The ControlObject used to the get the pitch range from the prefs.
678 ControlObjectThread *vinylStatus;
679 ControlObjectThread *rateDir; //direction of rate
680 ControlObjectThread *loopEnabled; //looping enabled?
681+ ControlObjectThread *signalenabled; //show the signal in the skin?
682 //ControlObject *vinylStatus; //Status of vinyl control
683
684 int iLeadInTime; //The lead-in time...
685@@ -86,6 +90,7 @@
686 float fRateRange; //The pitch range setting from Mixxx's preferences
687 float m_fTimecodeQuality; //Used as a measure of the quality of the timecode signal.
688
689+ float fTrackDuration;
690 unsigned long iSampleRate;
691 bool bIsEnabled;
692 int iRIAACorrection;
693
694=== modified file 'mixxx/src/vinylcontrol/vinylcontrolmanager.cpp'
695--- mixxx/src/vinylcontrol/vinylcontrolmanager.cpp 2011-07-19 20:54:56 +0000
696+++ mixxx/src/vinylcontrol/vinylcontrolmanager.cpp 2011-07-30 20:21:03 +0000
697@@ -26,11 +26,9 @@
698 {
699 // load a bunch of stuff
700 ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_enabled"))
701- ->queueFromThread(m_pConfig->getValueString(
702- ConfigKey("[VinylControl]","enabled_ch1")).toDouble());
703+ ->queueFromThread(0);
704 ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_enabled"))
705- ->queueFromThread(m_pConfig->getValueString(
706- ConfigKey("[VinylControl]","enabled_ch2")).toDouble());
707+ ->queueFromThread(0);
708 ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_mode"))
709 ->queueFromThread(m_pConfig->getValueString(
710 ConfigKey("[VinylControl]","mode")).toDouble());
711@@ -62,8 +60,6 @@
712
713 // save a bunch of stuff to config
714 // turn off vinyl control so it won't be enabled on load (this is redundant to mixxx.cpp)
715- m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch1"), false);
716- m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch2"), false);
717 m_pConfig->set(ConfigKey("[Channel 1]","vinylcontrol_enabled"), false);
718 m_pConfig->set(ConfigKey("[Channel 2]","vinylcontrol_enabled"), false);
719 m_pConfig->set(ConfigKey("[VinylControl]","mode"),
720
721=== modified file 'mixxx/src/vinylcontrol/vinylcontrolsignalwidget.cpp'
722--- mixxx/src/vinylcontrol/vinylcontrolsignalwidget.cpp 2011-04-17 04:16:00 +0000
723+++ mixxx/src/vinylcontrol/vinylcontrolsignalwidget.cpp 2011-07-30 20:21:03 +0000
724@@ -31,7 +31,7 @@
725 : QWidget(),
726 m_iTimerId(0),
727 m_pVinylControl(NULL),
728- m_iSize(128),
729+ m_iSize(100),
730 m_qImage(),
731 m_bVinylActive(FALSE) {
732 }
733
734=== modified file 'mixxx/src/vinylcontrol/vinylcontrolxwax.cpp'
735--- mixxx/src/vinylcontrol/vinylcontrolxwax.cpp 2011-05-21 01:07:25 +0000
736+++ mixxx/src/vinylcontrol/vinylcontrolxwax.cpp 2011-07-30 20:21:03 +0000
737@@ -47,6 +47,7 @@
738 iOldMode = MIXXX_VCMODE_ABSOLUTE;
739 dUiUpdateTime = -1.0f;
740 m_bNeedleSkipPrevention = (bool)(m_pConfig->getValueString( ConfigKey( "[VinylControl]", "needle_skip_prevention" ) ).toInt());
741+ signalenabled->slotSet(m_pConfig->getValueString( ConfigKey( "[VinylControl]", "show_signal_quality" ) ).toInt());
742
743 dLastTrackSelectPos = 0.0;
744 dCurTrackSelectPos = 0.0;
745@@ -97,6 +98,7 @@
746 //Note that timecoder_init will not double-malloc the LUTs, and after this we are guaranteed
747 //that the LUT has been generated unless we ran out of memory.
748 m_bLUTInitialized = true;
749+ m_uiSafeZone = timecoder_get_safe(&timecoder);
750 //}
751 s_xwaxLUTMutex.unlock();
752
753@@ -177,6 +179,7 @@
754 double dPitchRing[RING_SIZE];
755 int ringPos = 0;
756 int ringFilled = 0;
757+ double cur_duration = -1.0f;
758 double old_duration = -1.0f;
759 int reportedMode = 0;
760 bool reportedPlayButton = 0;
761@@ -225,36 +228,62 @@
762 //if no track loaded, let track selection work but that's it
763 if (duration == NULL)
764 {
765- bTrackSelectMode = true;
766- doTrackSelection(false, dVinylPitch, iPosition);
767+ //until I can figure out how to detect "track 2" on serato CD,
768+ //don't try track selection
769+ if (!m_bCDControl)
770+ {
771+ bTrackSelectMode = true;
772+ doTrackSelection(false, dVinylPitch, iPosition);
773+ }
774 continue;
775 }
776 //qDebug() << m_group << id << iPosition << dVinylPitch;
777
778- double cur_duration = duration->get();
779+ cur_duration = duration->get();
780+
781+
782+ //Has a new track been loaded?
783 //FIXME? we should really sync on all track changes
784 if (cur_duration != old_duration)
785 {
786 bForceResync=true;
787 bTrackSelectMode = false; //just in case
788 old_duration = cur_duration;
789+ //duration from the control object is an integer. We need
790+ //more precision:
791+ fTrackDuration = trackSamples->get() / 2 / trackSampleRate->get();
792+
793+ //we were at record end, so turn it off and restore mode
794+ if(atRecordEnd)
795+ {
796+ disableRecordEndMode();
797+ if (iOldMode == MIXXX_VCMODE_CONSTANT)
798+ iVCMode = MIXXX_VCMODE_RELATIVE;
799+ else
800+ iVCMode = iOldMode;
801+ }
802 }
803
804- dVinylPosition = iPosition;
805- dVinylPosition = dVinylPosition / 1000.0f;
806- dVinylPosition -= iLeadInTime;
807+ //make sure dVinylPosition only has good values
808+ if (iPosition != -1)
809+ {
810+ dVinylPosition = iPosition;
811+ dVinylPosition = dVinylPosition / 1000.0f;
812+ dVinylPosition -= iLeadInTime;
813+ }
814+
815+
816
817 //Initialize drift control to zero in case we don't get any position data to calculate it with.
818 dDriftControl = 0.0f;
819
820- filePosition = playPos->get() * cur_duration; //Get the playback position in the file in seconds.
821+ filePosition = playPos->get() * fTrackDuration; //Get the playback position in the file in seconds.
822
823 reportedMode = mode->get();
824 reportedPlayButton = playButton->get();
825
826 if (iVCMode != reportedMode)
827 {
828- //qDebug() << "cur mode" << iVCMode << "new mode" << reportedMode;
829 //if we are playing, don't allow change
830 //to absolute mode (would cause sudden track skip)
831 if (reportedPlayButton && reportedMode == MIXXX_VCMODE_ABSOLUTE)
832@@ -282,7 +311,6 @@
833 iVCMode = MIXXX_VCMODE_RELATIVE;
834 mode->slotSet((double)iVCMode);
835 }
836-
837 //are we newly playing near the end of the record? (in absolute mode, this happens
838 //when the filepos is past safe (more accurate),
839 //but it can also happen in relative mode if the vinylpos is nearing the end
840@@ -292,13 +320,13 @@
841 {
842 if (iVCMode == MIXXX_VCMODE_ABSOLUTE)
843 {
844- if ((filePosition + iLeadInTime) * 1000.0f > timecoder_get_safe(&timecoder) &&
845+ if ((filePosition + iLeadInTime) * 1000.0f > m_uiSafeZone &&
846 !bForceResync) //corner case: we are waiting for resync so don't enable just yet
847 enableRecordEndMode();
848 }
849 else if (iVCMode == MIXXX_VCMODE_RELATIVE || iVCMode == MIXXX_VCMODE_CONSTANT)
850 {
851- if (iPosition != -1 && iPosition > timecoder_get_safe(&timecoder))
852+ if (iPosition != -1 && iPosition > m_uiSafeZone)
853 enableRecordEndMode();
854 }
855 }
856@@ -307,25 +335,20 @@
857 {
858 //if atRecordEnd was true, maybe it no longer applies:
859
860- if ((iVCMode == MIXXX_VCMODE_ABSOLUTE &&
861- (filePosition + iLeadInTime) * 1000.0f <= timecoder_get_safe(&timecoder)))
862- {
863- //if we are in absolute mode and the file position is in a safe zone now
864- disableRecordEndMode();
865- }
866- else if (!reportedPlayButton)
867+ if (!reportedPlayButton)
868 {
869 //if we turned off play button, also disable
870 disableRecordEndMode();
871 }
872- else if (iPosition != -1)
873+ else if (iPosition != -1 &&
874+ iPosition <= m_uiSafeZone &&
875+ dVinylPosition > 0 &&
876+ checkSteadyPitch(dVinylPitch, filePosition) > 0.5)
877+
878 {
879- //if relative mode, and vinylpos is safe
880- if (iVCMode == MIXXX_VCMODE_RELATIVE &&
881- iPosition <= timecoder_get_safe(&timecoder))
882- {
883- disableRecordEndMode();
884- }
885+ //if good position, and safe, and not in leadin, and steady,
886+ //disable
887+ disableRecordEndMode();
888 }
889
890 if (atRecordEnd)
891@@ -345,17 +368,22 @@
892
893 if (!atRecordEnd)
894 {
895- if (iPosition != -1 && iPosition > timecoder_get_safe(&timecoder))
896+ if (iPosition != -1 && iPosition > m_uiSafeZone)
897 {
898- if (!bTrackSelectMode)
899+ //until I can figure out how to detect "track 2" on serato CD,
900+ //don't try track selection
901+ if (!m_bCDControl)
902 {
903- qDebug() << "position greater than safe, select mode" << iPosition << timecoder_get_safe(&timecoder);
904- bTrackSelectMode = true;
905- togglePlayButton(FALSE);
906- resetSteadyPitch(0.0f, 0.0f);
907- controlScratch->slotSet(0.0f);
908+ if (!bTrackSelectMode)
909+ {
910+ qDebug() << "position greater than safe, select mode" << iPosition << m_uiSafeZone;
911+ bTrackSelectMode = true;
912+ togglePlayButton(FALSE);
913+ resetSteadyPitch(0.0f, 0.0f);
914+ controlScratch->slotSet(0.0f);
915+ }
916+ doTrackSelection(true, dVinylPitch, iPosition);
917 }
918- doTrackSelection(true, dVinylPitch, iPosition);
919
920 //hm I wonder if track will keep playing while this happens?
921 //not sure what we want to do here... probably enforce
922@@ -432,8 +460,9 @@
923
924 //save the absolute amount of drift for when we need to estimate vinyl position
925 dDriftAmt = dVinylPosition - filePosition;
926+
927+ //qDebug() << "drift" << dDriftAmt;
928
929- //qDebug() << "vinyl" << dVinylPosition << "file" << filePosition;
930 if (bForceResync)
931 {
932 //if forceresync was set but we're no longer absolute,
933@@ -504,12 +533,14 @@
934
935 //Calculate how much the vinyl's position has drifted from it's timecode and compensate for it.
936 //(This is caused by the manufacturing process of the vinyl.)
937- dDriftControl = ((filePosition - dVinylPosition) / dVinylPosition) / 100 * 4.0f;
938+ if (fabs(dDriftAmt) > 0.1 && fabs(dDriftAmt) < 5.0) {
939+ dDriftControl = dDriftAmt;
940+ } else {
941+ dDriftControl = 0.0;
942+ }
943
944 //if we hit the end of the ring, loop around
945- ringPos++;
946- if(ringPos >= RING_SIZE)
947- ringPos = 0;
948+ ringPos = (ringPos + 1) % RING_SIZE;
949 dOldPos = dVinylPosition;
950 }
951 else
952@@ -528,6 +559,14 @@
953 ringFilled = 0;
954 continue;
955 }
956+
957+ if (iVCMode == MIXXX_VCMODE_ABSOLUTE &&
958+ fabs(dVinylPitch) < 0.05 &&
959+ fabs(dDriftAmt) >= 0.3f)
960+ {
961+ qDebug() << "slow, out of sync, syncing position";
962+ syncPosition();
963+ }
964
965 dOldPos = filePosition + dDriftAmt;
966
967@@ -556,13 +595,12 @@
968 else
969 averagePitch = dVinylPitch;
970
971-
972 if (iVCMode == MIXXX_VCMODE_ABSOLUTE)
973 {
974- controlScratch->slotSet(averagePitch + dDriftControl);
975+ controlScratch->slotSet(dVinylPitch + dDriftControl);
976 if (iPosition != -1 && reportedPlayButton && uiUpdateTime(filePosition))
977 {
978- rateSlider->slotSet(rateDir->get() * (fabs(averagePitch + dDriftControl) - 1.0f) / fRateRange);
979+ rateSlider->slotSet(rateDir->get() * (fabs(dVinylPitch + dDriftControl) - 1.0f) / fRateRange);
980 dUiUpdateTime = filePosition;
981 }
982 }
983@@ -587,14 +625,21 @@
984 //let the track play a wee bit more before deciding we've stopped
985
986 rateSlider->slotSet(0.0f);
987+
988+ if (iVCMode == MIXXX_VCMODE_ABSOLUTE &&
989+ fabs(dVinylPosition - filePosition) >= 0.1f)
990+ {
991+ qDebug() << "stopped, out of sync, syncing position";
992+ syncPosition();
993+ }
994
995 if(fabs(filePosition - dOldFilePos) >= 0.1 ||
996 !m_bNeedleSkipPrevention ||
997 filePosition == dOldFilePos)
998 {
999 //We are not playing any more
1000- togglePlayButton(FALSE);
1001- resetSteadyPitch(0.0f, 0.0f);
1002+ togglePlayButton(FALSE);
1003+ resetSteadyPitch(0.0f, 0.0f);
1004 controlScratch->slotSet(0.0f);
1005 //resetSteadyPitch(dVinylPitch, filePosition);
1006 //Notify the UI that the timecode quality is garbage/missing.
1007@@ -643,15 +688,8 @@
1008 {
1009 vinylStatus->slotSet(VINYL_STATUS_OK);
1010 atRecordEnd = false;
1011- //don't start a new track with constant mode
1012- if (iVCMode == MIXXX_VCMODE_CONSTANT)
1013- {
1014- if (iOldMode == MIXXX_VCMODE_CONSTANT)
1015- iVCMode = MIXXX_VCMODE_RELATIVE;
1016- else
1017- iVCMode = iOldMode;
1018- mode->slotSet((double)iVCMode);
1019- }
1020+ iVCMode = MIXXX_VCMODE_RELATIVE;
1021+ mode->slotSet((double)iVCMode);
1022 }
1023
1024 void VinylControlXwax::togglePlayButton(bool on)
1025@@ -769,11 +807,19 @@
1026 void VinylControlXwax::syncPosition()
1027 {
1028 //qDebug() << "sync position" << dVinylPosition / duration->get();
1029- vinylSeek->slotSet(dVinylPosition / duration->get()); //VinylPos in seconds / total length of song
1030+ vinylSeek->slotSet(dVinylPosition / fTrackDuration); //VinylPos in seconds / total length of song
1031 }
1032
1033 bool VinylControlXwax::checkEnabled(bool was, bool is)
1034 {
1035+ // if we're not enabled, but the last object was, try turning ourselves on
1036+ // XXX: is this just a race that's working right now?
1037+ if (!is and wantenabled->get())
1038+ {
1039+ enabled->slotSet(true);
1040+ wantenabled->slotSet(false); //don't try to do this over and over
1041+ return true; //optimism!
1042+ }
1043 if (was != is)
1044 {
1045 //we reset the scratch value, but we don't reset the rate slider.
1046@@ -824,7 +870,9 @@
1047 {
1048 bQualityRing[iQualPos] = quality_sample;
1049 if(iQualFilled < QUALITY_RING_SIZE)
1050- iQualFilled++;
1051+ {
1052+ iQualFilled++;
1053+ }
1054
1055 int quality = 0;
1056 for (int i=0; i<iQualFilled; i++)
1057@@ -836,9 +884,7 @@
1058 //qDebug() << "quality" << m_fTimecodeQuality;
1059 m_fTimecodeQuality = (float)quality / (float)iQualFilled;
1060
1061- iQualPos++;
1062- if(iQualPos >= QUALITY_RING_SIZE)
1063- iQualPos = 0;
1064+ iQualPos = (iQualPos + 1) % QUALITY_RING_SIZE;
1065 }
1066
1067 float VinylControlXwax::getAngle()
1068
1069=== modified file 'mixxx/src/vinylcontrol/vinylcontrolxwax.h'
1070--- mixxx/src/vinylcontrol/vinylcontrolxwax.h 2011-04-17 04:16:00 +0000
1071+++ mixxx/src/vinylcontrol/vinylcontrolxwax.h 2011-07-30 20:21:03 +0000
1072@@ -48,6 +48,7 @@
1073 void establishQuality(bool quality_sample);
1074
1075 double dFileLength; // The length (in samples) of the current song.
1076+ unsigned int m_uiSafeZone; // Cache the position of the end of record
1077
1078 double dOldPos; // The position read last time it was polled.
1079 double dOldPitch;
1080
1081=== modified file 'mixxx/src/waveform/waveformrenderer.cpp'
1082--- mixxx/src/waveform/waveformrenderer.cpp 2011-04-06 21:20:35 +0000
1083+++ mixxx/src/waveform/waveformrenderer.cpp 2011-07-30 20:21:03 +0000
1084@@ -26,6 +26,8 @@
1085 #define DEFAULT_SUBPIXELS_PER_PIXEL 4
1086 #define DEFAULT_PIXELS_PER_SECOND 100
1087
1088+#define RATE_INCREMENT 0.015
1089+
1090 void WaveformRenderer::run() {
1091 double msecs_old = 0, msecs_elapsed = 0;
1092
1093@@ -61,6 +63,7 @@
1094 m_dRate(0),
1095 m_dRateRange(0),
1096 m_dRateDir(0),
1097+ m_iRateAdjusting(0),
1098 m_iDupes(0),
1099 m_dPlayPosAdjust(0),
1100 m_iLatency(0),
1101@@ -190,7 +193,7 @@
1102 }
1103
1104 void WaveformRenderer::slotUpdateRate(double v) {
1105- m_dRate = v;
1106+ m_dTargetRate = v;
1107 }
1108
1109 void WaveformRenderer::slotUpdateRateRange(double v) {
1110@@ -501,6 +504,26 @@
1111
1112 //qDebug() << m_dPlayPosAdjust;
1113
1114+ // Gradually stretch the waveform
1115+ if (fabs(m_dTargetRate - m_dRate) > RATE_INCREMENT)
1116+ {
1117+ if ((m_dTargetRate - m_dRate) > 0)
1118+ {
1119+ m_iRateAdjusting = m_iRateAdjusting > 0 ? m_iRateAdjusting + 1 : 1;
1120+ m_dRate = math_min(m_dTargetRate, m_dRate + RATE_INCREMENT * pow(m_iRateAdjusting, 2) / 80);
1121+ }
1122+ else
1123+ {
1124+ m_iRateAdjusting = m_iRateAdjusting < 0 ? m_iRateAdjusting - 1 : -1;
1125+ m_dRate = math_max(m_dTargetRate, m_dRate - RATE_INCREMENT * pow(m_iRateAdjusting, 2) / 80);
1126+ }
1127+ }
1128+ else
1129+ {
1130+ m_iRateAdjusting = 0;
1131+ m_dRate = m_dTargetRate;
1132+ }
1133+
1134 // Limit our rate adjustment to < 99%, "Bad Things" might happen otherwise.
1135 double rateAdjust = m_dRateDir * math_min(0.99, m_dRate * m_dRateRange);
1136
1137
1138=== modified file 'mixxx/src/waveform/waveformrenderer.h'
1139--- mixxx/src/waveform/waveformrenderer.h 2011-03-08 22:17:41 +0000
1140+++ mixxx/src/waveform/waveformrenderer.h 2011-07-30 20:21:03 +0000
1141@@ -61,7 +61,8 @@
1142
1143 int m_iPlayPosTime, m_iPlayPosTimeOld;
1144 QTime m_playPosTime, m_playPosTimeOld;
1145- double m_dPlayPos, m_dPlayPosOld, m_dRate, m_dRateRange, m_dRateDir;
1146+ double m_dPlayPos, m_dPlayPosOld, m_dTargetRate, m_dRate, m_dRateRange, m_dRateDir;
1147+ int m_iRateAdjusting;
1148 int m_iDupes;
1149 double m_dPlayPosAdjust;
1150 int m_iLatency;
1151
1152=== modified file 'mixxx/src/widget/wspinny.cpp'
1153--- mixxx/src/widget/wspinny.cpp 2011-05-12 14:46:18 +0000
1154+++ mixxx/src/widget/wspinny.cpp 2011-07-30 20:21:03 +0000
1155@@ -6,7 +6,7 @@
1156 #include "sharedglcontext.h"
1157 #include "wspinny.h"
1158
1159-WSpinny::WSpinny(QWidget* parent) : QGLWidget(SharedGLContext::getContext(), parent),
1160+WSpinny::WSpinny(QWidget* parent, VinylControlManager* pVCMan) : QGLWidget(SharedGLContext::getContext(), parent),
1161 m_pBG(NULL),
1162 m_pFG(NULL),
1163 m_pGhost(NULL),
1164@@ -20,6 +20,12 @@
1165 m_pScratchToggle(NULL),
1166 m_pScratchPos(NULL),
1167 m_pVinylControlSpeedType(NULL),
1168+ m_pVinylControlEnabled(NULL),
1169+ m_bVinylActive(false),
1170+ m_bSignalActive(true),
1171+ m_iSize(0),
1172+ m_iTimerId(0),
1173+ m_iSignalUpdateTick(0),
1174 m_fAngle(0.0f),
1175 m_fGhostAngle(0.0f),
1176 m_dPausedPosition(0.0f),
1177@@ -29,6 +35,10 @@
1178 m_iFullRotations(0),
1179 m_dPrevTheta(0.)
1180 {
1181+#ifdef __VINYLCONTROL__
1182+ m_pVCManager = pVCMan;
1183+ m_pVinylControl = NULL;
1184+#endif
1185 //Drag and drop
1186 setAcceptDrops(true);
1187 }
1188@@ -69,6 +79,13 @@
1189 if (m_pBG && !m_pBG->isNull()) {
1190 setFixedSize(m_pBG->size());
1191 }
1192+
1193+#ifdef __VINYLCONTROL__
1194+ m_iSize = MIXXX_VINYL_SCOPE_SIZE;
1195+ m_qImage = QImage(m_iSize, m_iSize, QImage::Format_ARGB32);
1196+ //fill with transparent black
1197+ m_qImage.fill(qRgba(0,0,0,0));
1198+#endif
1199
1200 m_pPlay = new ControlObjectThreadMain(ControlObject::getControl(
1201 ConfigKey(group, "play")));
1202@@ -92,6 +109,15 @@
1203 ConfigKey(group, "scratch_position_enable")));
1204 m_pScratchPos = new ControlObjectThreadMain(ControlObject::getControl(
1205 ConfigKey(group, "scratch_position")));
1206+
1207+ Q_ASSERT(m_pPlayPos);
1208+ Q_ASSERT(m_pDuration);
1209+
1210+ //Repaint when visual_playposition changes.
1211+ connect(m_pVisualPlayPos, SIGNAL(valueChanged(double)),
1212+ this, SLOT(updateAngle(double)));
1213+
1214+#ifdef __VINYLCONTROL__
1215 m_pVinylControlSpeedType = new ControlObjectThreadMain(ControlObject::getControl(
1216 ConfigKey(group, "vinylcontrol_speed_type")));
1217 if (m_pVinylControlSpeedType)
1218@@ -99,17 +125,26 @@
1219 //Initialize the rotational speed.
1220 this->updateVinylControlSpeed(m_pVinylControlSpeedType->get());
1221 }
1222- Q_ASSERT(m_pPlayPos);
1223- Q_ASSERT(m_pDuration);
1224-
1225- //Repaint when visual_playposition changes.
1226- connect(m_pVisualPlayPos, SIGNAL(valueChanged(double)),
1227- this, SLOT(updateAngle(double)));
1228+ m_pVinylControlEnabled = new ControlObjectThreadMain(ControlObject::getControl(
1229+ ConfigKey(group, "vinylcontrol_enabled")));
1230+ m_pSignalEnabled = new ControlObjectThreadMain(ControlObject::getControl(
1231+ ConfigKey(group, "vinylcontrol_signal_enabled")));
1232+ m_pRate = new ControlObjectThreadMain(ControlObject::getControl(
1233+ ConfigKey(group, "rate")));
1234
1235 //Match the vinyl control's set RPM so that the spinny widget rotates at the same
1236 //speed as your physical decks, if you're using vinyl control.
1237 connect(m_pVinylControlSpeedType, SIGNAL(valueChanged(double)),
1238 this, SLOT(updateVinylControlSpeed(double)));
1239+
1240+ //Make sure vinyl control proxies are up to date
1241+ connect(m_pVinylControlEnabled, SIGNAL(valueChanged(double)),
1242+ this, SLOT(updateVinylControlEnabled(double)));
1243+
1244+ //Check the rate to see if we are stopped
1245+ connect(m_pRate, SIGNAL(valueChanged(double)),
1246+ this, SLOT(updateRate(double)));
1247+#endif
1248 }
1249
1250 void WSpinny::paintEvent(QPaintEvent *e)
1251@@ -121,6 +156,49 @@
1252 if (m_pBG) {
1253 p.drawPixmap(0, 0, *m_pBG);
1254 }
1255+
1256+#ifdef __VINYLCONTROL__
1257+ // Overlay the signal quality drawing if vinyl is active
1258+ if (m_bVinylActive && m_bSignalActive)
1259+ {
1260+ //reduce cpu load by only updating every 3 times
1261+ m_iSignalUpdateTick = (m_iSignalUpdateTick + 1) % 3;
1262+ if (m_iSignalUpdateTick == 0)
1263+ {
1264+ unsigned char * buf = m_pVinylControl->getScopeBytemap();
1265+ int r,g,b;
1266+ QColor qual_color = QColor();
1267+ float signalQuality = m_pVinylControl->getTimecodeQuality();
1268+
1269+ //color is related to signal quality
1270+ //hsv: s=1, v=1
1271+ //h is the only variable.
1272+ //h=0 is red, h=120 is green
1273+ qual_color.setHsv((int)(120.0 * signalQuality), 255, 255);
1274+ qual_color.getRgb(&r, &g, &b);
1275+
1276+ if (buf) {
1277+ for (int y=0; y<m_iSize; y++) {
1278+ QRgb *line = (QRgb *)m_qImage.scanLine(y);
1279+ for(int x=0; x<m_iSize; x++) {
1280+ //use xwax's bitmap to set alpha data only
1281+ //adjust alpha by 3/4 so it's not quite so distracting
1282+ //setpixel is slow, use scanlines instead
1283+ //m_qImage.setPixel(x, y, qRgba(r,g,b,(int)buf[x+m_iSize*y] * .75));
1284+ *line = qRgba(r,g,b,(int)(buf[x+m_iSize*y] * .75));
1285+ line++;
1286+ }
1287+ }
1288+ p.drawImage(this->rect(), m_qImage);
1289+ }
1290+ }
1291+ else
1292+ {
1293+ //draw the last good image
1294+ p.drawImage(this->rect(), m_qImage);
1295+ }
1296+ }
1297+#endif
1298
1299 //To rotate the foreground pixmap around the center of the image,
1300 //we use the classic trick of translating the coordinate system such that
1301@@ -147,7 +225,7 @@
1302 //Rotate back to the playback position (not the ghost positon),
1303 //and draw the beat marks from there.
1304 p.restore();
1305-
1306+
1307 /*
1308 //Draw a line where the next 4 beats are
1309 double bpm = m_pBPM->get();
1310@@ -247,6 +325,29 @@
1311 void WSpinny::updateAngle(double playpos)
1312 {
1313 m_fAngle = calculateAngle(playpos);
1314+
1315+ // if we had the timer going, kill it
1316+ if (m_iTimerId != 0) {
1317+ killTimer(m_iTimerId);
1318+ m_iTimerId = 0;
1319+ }
1320+ update();
1321+}
1322+
1323+void WSpinny::updateRate(double rate)
1324+{
1325+ //if rate is zero, updateAngle won't get called,
1326+ if (rate == 0.0 && m_bVinylActive)
1327+ {
1328+ if (m_iTimerId == 0)
1329+ {
1330+ m_iTimerId = startTimer(10);
1331+ }
1332+ }
1333+}
1334+
1335+void WSpinny::timerEvent(QTimerEvent *event)
1336+{
1337 update();
1338 }
1339
1340@@ -266,6 +367,60 @@
1341 m_dRotationsPerSecond = rpm/60.;
1342 }
1343
1344+void WSpinny::updateVinylControlEnabled(double enabled)
1345+{
1346+#ifdef __VINYLCONTROL__
1347+ if (enabled)
1348+ {
1349+ if (m_pVinylControl == NULL)
1350+ {
1351+ QList<VinylControlProxy*> VCProxiesList = m_pVCManager->vinylControlProxies();
1352+ if (m_group == "[Channel1]")
1353+ {
1354+ m_pVinylControl = VCProxiesList.value(0);
1355+ }
1356+ else if (m_group == "[Channel2]")
1357+ {
1358+ m_pVinylControl = VCProxiesList.value(1);
1359+ }
1360+
1361+ if (m_pVinylControl != NULL)
1362+ {
1363+ m_bVinylActive = true;
1364+ m_bSignalActive = m_pSignalEnabled->get();
1365+ connect(m_pVinylControl, SIGNAL(destroyed()),
1366+ this, SLOT(invalidateVinylControl()));
1367+ }
1368+ }
1369+ else
1370+ {
1371+ m_bVinylActive = true;
1372+ }
1373+ }
1374+ else
1375+ {
1376+ m_bVinylActive = false;
1377+ //don't need the timer anymore
1378+ if (m_iTimerId != 0)
1379+ {
1380+ killTimer(m_iTimerId);
1381+ }
1382+ // draw once more to erase signal
1383+ update();
1384+ }
1385+#endif
1386+}
1387+
1388+void WSpinny::invalidateVinylControl()
1389+{
1390+#ifdef __VINYLCONTROL__
1391+ m_bVinylActive = false;
1392+ m_pVinylControl = NULL;
1393+ update();
1394+#endif
1395+}
1396+
1397+
1398 void WSpinny::mouseMoveEvent(QMouseEvent * e)
1399 {
1400 int y = e->y();
1401@@ -301,7 +456,7 @@
1402 //qDebug() << "c t:" << theta << "pt:" << m_dPrevTheta <<
1403 // "icr" << m_iFullRotations;
1404
1405- if (e->buttons() & Qt::LeftButton)
1406+ if (e->buttons() & Qt::LeftButton && !m_bVinylActive)
1407 {
1408 //Convert deltaTheta into a percentage of song length.
1409 double absPos = calculatePositionFromAngle(theta);
1410@@ -325,6 +480,10 @@
1411
1412 m_iStartMouseX = x;
1413 m_iStartMouseY = y;
1414+
1415+ //don't do anything if vinyl control is active
1416+ if (m_bVinylActive)
1417+ return;
1418
1419 if (e->button() == Qt::LeftButton)
1420 {
1421@@ -394,7 +553,7 @@
1422 Q_UNUSED(e); //ditch unused param warning
1423
1424 /*
1425- double wheelDirection = ((QWheelEvent *)e)->delta() / 120.;
1426+ double wheelDirection = ((QWheelEvent *)e)->delta() / 120.;
1427 double newValue = getValue() + (wheelDirection);
1428 this->updateValue(newValue);
1429
1430
1431=== modified file 'mixxx/src/widget/wspinny.h'
1432--- mixxx/src/widget/wspinny.h 2011-05-11 04:38:17 +0000
1433+++ mixxx/src/widget/wspinny.h 2011-07-30 20:21:03 +0000
1434@@ -4,6 +4,11 @@
1435
1436 #include <QGLWidget>
1437 #include "wwidget.h"
1438+#include "vinylcontrol/vinylcontrolmanager.h"
1439+#ifdef __VINYLCONTROL__
1440+#include "vinylcontrol/vinylcontrolproxy.h"
1441+#include "vinylcontrol/vinylcontrol.h"
1442+#endif
1443
1444 class ControlObjectThreadMain;
1445
1446@@ -11,15 +16,18 @@
1447 {
1448 Q_OBJECT
1449 public:
1450- WSpinny(QWidget* parent);
1451+ WSpinny(QWidget* parent, VinylControlManager* pVCMan);
1452 ~WSpinny();
1453 void setup(QDomNode node, QString group);
1454 void dragEnterEvent(QDragEnterEvent *event);
1455 void dropEvent(QDropEvent *event);
1456 public slots:
1457 void updateAngle(double);
1458+ void updateRate(double);
1459 void updateAngleForGhost();
1460 void updateVinylControlSpeed(double rpm);
1461+ void updateVinylControlEnabled(double enabled);
1462+ void invalidateVinylControl();
1463 signals:
1464 void trackDropped(QString filename, QString group);
1465 protected:
1466@@ -29,6 +37,7 @@
1467 void mousePressEvent(QMouseEvent * e);
1468 void mouseReleaseEvent(QMouseEvent * e);
1469 void wheelEvent(QWheelEvent *e);
1470+ void timerEvent(QTimerEvent* event);
1471
1472 double calculateAngle(double playpos);
1473 int calculateFullRotations(double playpos);
1474@@ -47,7 +56,22 @@
1475 ControlObjectThreadMain* m_pScratch;
1476 ControlObjectThreadMain* m_pScratchToggle;
1477 ControlObjectThreadMain* m_pScratchPos;
1478+ ControlObjectThreadMain* m_pRate;
1479 ControlObjectThreadMain* m_pVinylControlSpeedType;
1480+ ControlObjectThreadMain* m_pVinylControlEnabled;
1481+ ControlObjectThreadMain* m_pSignalEnabled;
1482+
1483+#ifdef __VINYLCONTROL__
1484+ VinylControlManager* m_pVCManager;
1485+ VinylControlProxy* m_pVinylControl;
1486+#endif
1487+ bool m_bVinylActive;
1488+ bool m_bSignalActive;
1489+ QImage m_qImage;
1490+ int m_iSize;
1491+ int m_iTimerId;
1492+ int m_iSignalUpdateTick;
1493+
1494 QString m_group;
1495 float m_fAngle; //Degrees
1496 float m_fGhostAngle;

Subscribers

People subscribed via source and target branches