Merge lp:~mixxxdevelopers/mixxx/features_vcman into lp:~mixxxdevelopers/mixxx/trunk

Proposed by William Good
Status: Merged
Merged at revision: 2757
Proposed branch: lp:~mixxxdevelopers/mixxx/features_vcman
Merge into: lp:~mixxxdevelopers/mixxx/trunk
Diff against target: 978 lines (+268/-207)
21 files modified
mixxx/build/features.py (+6/-5)
mixxx/src/dlgpreferences.cpp (+3/-4)
mixxx/src/dlgpreferences.h (+2/-1)
mixxx/src/dlgprefsound.cpp (+0/-16)
mixxx/src/dlgprefvinyl.cpp (+18/-41)
mixxx/src/dlgprefvinyl.h (+4/-10)
mixxx/src/engine/enginebuffer.cpp (+2/-2)
mixxx/src/engine/enginebuffer.h (+1/-1)
mixxx/src/engine/vinylcontrolcontrol.cpp (+1/-1)
mixxx/src/mixxx.cpp (+27/-26)
mixxx/src/mixxx.h (+3/-4)
mixxx/src/soundmanager.cpp (+0/-57)
mixxx/src/soundmanager.h (+0/-10)
mixxx/src/vinylcontrol/vinylcontrol.cpp (+3/-3)
mixxx/src/vinylcontrol/vinylcontrol.h (+4/-4)
mixxx/src/vinylcontrol/vinylcontrolmanager.cpp (+148/-0)
mixxx/src/vinylcontrol/vinylcontrolmanager.h (+36/-0)
mixxx/src/vinylcontrol/vinylcontrolproxy.cpp (+5/-14)
mixxx/src/vinylcontrol/vinylcontrolproxy.h (+2/-5)
mixxx/src/vinylcontrol/vinylcontrolxwax.cpp (+2/-2)
mixxx/src/vinylcontrol/vinylcontrolxwax.h (+1/-1)
To merge this branch: bzr merge lp:~mixxxdevelopers/mixxx/features_vcman
Reviewer Review Type Date Requested Status
RJ Skerry-Ryan Approve
Review via email: mp+58019@code.launchpad.net

Description of the change

Branch:
* Moves all the vinyl control code to src/vinylcontrol/
* Moves all the vinyl control code from SoundManager to new VinylControlManager
* Sets VinylControlManager as the designated recipient of vinyl control samples from SoundManager

Features:
* Vinyl control prefs can now be applied without rebooting the portaudio callback (not a particularly useful feature but nice to keep unrelated things uncoupled)
* SoundManager now 100% unaware of vinyl control, as it ought to be.
* More stuff here I'm probably not thinking of

Bugs (???):
* The ordering in the sound prefs under the input tab is weird on my machine (order: VC1, mic, VC2). This is due to some weird Qt signal ordering, because the add-audiodest-to-prefs code is run before the event loop starts, we're at qt's mercy when it comes to spitting out signals in the same order it receives them (and it doesn't). I'll worry about this in trunk since that's where the bug (if you can call it that) is, I'll probably just do some intelligent sorting in DlgPrefSound.
* Regressions??? I've tested messing with config, single deck vinyl, both-deck vinyl. I think it's good, but testers are always great.

Please excuse any glaring errors, brain is a bit numb and eyes are a bit tired.

To post a comment you must log in.
2655. By William Good

Merge with lp:mixxx

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

Hey Bill,

Looking good -- here are my comments:

* In VinylControlManager, it's a little sketchy to me that SoundManager is passed in and that it's used to scan through its list of enabled inputs -- seems like VCManager shouldn't know those details of SoundManager. Would it be possible to determine which VC decks were enabled by just keeping track of onInputConnect/onInputDisconnect calls? Also naming the parameter 'deck' is a little misleading since one turntable can control multiple decks (or will in the future?) Since you're checking for a matching AudioInput index, doesn't this just test whether the N'th VC input is enabled? Anyway I would just replace this with a QSet<AudioInput> that you add to onInputConnect and remove from onInputDisconnect, that way you can just make this test whether an appropriate AudioInput is in the set.

* I don't think I understand how QSemaphore protects m_proxies in this case. QList is not thread safe so two threads should never access it at once -- this includes using QList::at, so all accesses to the list should be guarded by a monolithic QMutex (yea .. it sucks). I would use a QMutex and then make sure to unlock it the second you get the VCProxy that you need from the list (or in the case of creating the VC proxy, create it, then lock and insert it and unlock).

Otherwise everything seems fine to me -- we should have someone test it out first to verify that it actually works ;)

review: Needs Fixing
2656. By William Good

Delete vcmanager before the engine to prevent a segfault on deref of a CO on exit

2657. By William Good

Move the vinyl control proxies to an array-based QVector (should be faster? also more in line with how I was using the data structure anyway)

2658. By William Good

Remove SoundManager usage from VinylControlManager

Revision history for this message
William Good (bkgood) wrote :

> * In VinylControlManager, it's a little sketchy to me that SoundManager is
> passed in and that it's used to scan through its list of enabled inputs --
> seems like VCManager shouldn't know those details of SoundManager. Would
> it be possible to determine which VC decks were enabled by just keeping
> track of onInputConnect/onInputDisconnect calls?

Fixed... ended up being way simpler once I wasn't just doing a straight copy+paste from the old code.

> Also naming the parameter
> 'deck' is a little misleading since one turntable can control multiple
> decks (or will in the future?) Since you're checking for a matching
> AudioInput index, doesn't this just test whether the N'th VC input is
> enabled?

The 'deck' parameter actually refers to the deck which the vinyl control input is to control (so deck=1 refers to [Channel1] stuff), so aside from perhaps misguided naming, I think this is correct. But yes, this just makes life easier (saves some code duplication) for some GUI code in mixxx.cpp.

> * I don't think I understand how QSemaphore protects m_proxies in this
> case. QList is not thread safe so two threads should never access it at
> once -- this includes using QList::at, so all accesses to the list should
> be guarded by a monolithic QMutex (yea .. it sucks). I would use a QMutex
> and then make sure to unlock it the second you get the VCProxy that you
> need from the list (or in the case of creating the VC proxy, create it,
> then lock and insert it and unlock).
>

Is QList::at (now QVector::at) really not save to call concurrently? I had a look at the Qt source and it looks like a totally safe operation (immediately, ::at is const so state isn't being modified). The only case I could think of in which this would be a problem is if the list was being modified while ::at was called, which was how I came to the semaphore use: any number of callback threads (which will never be greater than the number of vinyl control objects) can call receiveBuffer and submit samples, but writing requires a total lockout of all list readers so I acquire all of the semaphore's 'resources' (and block until I do) before doing any modification. As I only allocate memory for the vector once and simply replace elements afterwards, I'm wondering if I could just make a mutex for each individual vector slot and use that to keep from replacing a pointer while I'm reading it in another thread.

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

Some minor fixes below but looks good to me.

> Is QList::at (now QVector::at) really not save to call concurrently?

Basically, no none of them are. The Qt docs don't claim they are thread safe at all. While you're right, the many-reader case will generally not cause issues since it doesn't update state we don't have guarantees that the list/vector isn't being grown/shrunk when we do something to it.

You're assuming that m_proxies never changes. Things like m_proxies.size() aren't ok to call without a lock protecting the entire list if the size of that list changes. Today it's a safe assumption that m_proxies never changes, so they should happen to work fine, but in the future we might change things and forget to update the locking strategy for m_proxies. I would switch to using a QReadWriteLock just to be safe.. it allows many readers concurrently but locks them out when someone is locking it for writing.

- In mixxx.cpp the else block sets m_pVCManager to NULL, but this variable doesn't exist if VINYLCONTROL isn't defined.

Today we don't really support updating the # of decks on the fly and there are only as many spots for proxies as there are physical decks. I'm a little wary of passing in the number of decks a fixed value that doesn't change because this will be a pain later when potentially we let you add decks to Mixxx on the fly, or when the skin can specify how many decks it's made for, etc. etc. What I mean is that it isn't un-imaginable that the number of decks could change on the fly. We can fix this when we n-deck'ify vinyl control though.

review: Approve
2659. By William Good

Move fun semaphore locking to QReadWriteLock

2660. By William Good

Always declare VinylControlManager instance in MixxxApp

2661. By William Good

Don't hardcode VinylControlManager to a set number of VinylControlProxies, allow arbitrary number.

Revision history for this message
William Good (bkgood) wrote :

> You're assuming that m_proxies never changes. Things like m_proxies.size()
> aren't ok to call without a lock protecting the entire list if the size of
> that list changes. Today it's a safe assumption that m_proxies never changes,
> so they should happen to work fine, but in the future we might change things
> and forget to update the locking strategy for m_proxies. I would switch to
> using a QReadWriteLock just to be safe.. it allows many readers concurrently
> but locks them out when someone is locking it for writing.
>

Indeed, I wrote my locking strategy under the assumptions of how I wrote the code today and not how it might be modified in a year, but I don't guess I see this as making it particularly wrong -- but QReadWriteLock does everything I want, and that's the more obvious approach anyway.

> - In mixxx.cpp the else block sets m_pVCManager to NULL, but this variable
> doesn't exist if VINYLCONTROL isn't defined.
>
Good catch, I have to have it declared as it's passed to the DlgPreferences ctor (which is why it's NULLed) but I think I discovered this after I wrote the VinylControlManager instance into mixxx.h.

> Today we don't really support updating the # of decks on the fly and there are
> only as many spots for proxies as there are physical decks. I'm a little wary
> of passing in the number of decks a fixed value that doesn't change because
> this will be a pain later when potentially we let you add decks to Mixxx on
> the fly, or when the skin can specify how many decks it's made for, etc. etc.
> What I mean is that it isn't un-imaginable that the number of decks could
> change on the fly. We can fix this when we n-deck'ify vinyl control though.

VinylControlManager will now create a VinylControlProxy for whatever index it receives, from 0 to 255 (and why _not_ support 256 decks, VDJ has 99...). I didn't bother to mess with the big config-load/save blocks, those will have to be fixed (i.e. generalized and iterated-over) for n-decks.

Let me know about these changes and I'll merge into trunk if I still get the thumbs-up, thanks for looking at it! fyi, I've tested using a couple of instances of mixxx and crazy jack routing so I'm fairly confident in its correctness, at least in the cases I tested it.

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'mixxx/build/features.py'
2--- mixxx/build/features.py 2011-04-17 02:42:45 +0000
3+++ mixxx/build/features.py 2011-04-18 08:02:27 +0000
4@@ -287,12 +287,13 @@
5 build.env.Append(CPPPATH='#lib/scratchlib')
6
7 def sources(self, build):
8- sources = ['vinylcontrol.cpp',
9- 'vinylcontrolproxy.cpp',
10- 'vinylcontrolxwax.cpp',
11+ sources = ['vinylcontrol/vinylcontrol.cpp',
12+ 'vinylcontrol/vinylcontrolproxy.cpp',
13+ 'vinylcontrol/vinylcontrolxwax.cpp',
14 'dlgprefvinyl.cpp',
15- 'vinylcontrolsignalwidget.cpp',
16- 'engine/vinylcontrolcontrol.cpp']
17+ 'vinylcontrol/vinylcontrolsignalwidget.cpp',
18+ 'vinylcontrol/vinylcontrolmanager.cpp',
19+ 'engine/vinylcontrolcontrol.cpp',]
20 if build.platform_is_windows:
21 sources.append("#lib/xwax/timecoder_win32.cpp")
22 sources.append("#lib/xwax/lut.cpp")
23
24=== modified file 'mixxx/src/dlgpreferences.cpp'
25--- mixxx/src/dlgpreferences.cpp 2011-04-16 20:03:36 +0000
26+++ mixxx/src/dlgpreferences.cpp 2011-04-18 08:02:27 +0000
27@@ -50,7 +50,8 @@
28
29 DlgPreferences::DlgPreferences(MixxxApp * mixxx, SkinLoader* pSkinLoader,
30 SoundManager * soundman, PlayerManager* pPlayerManager,
31- MidiDeviceManager * midi, ConfigObject<ConfigValue> * _config)
32+ MidiDeviceManager * midi, VinylControlManager *pVCManager,
33+ ConfigObject<ConfigValue> * _config)
34 : QDialog(), Ui::DlgPreferencesDlg() {
35 m_pMixxx = mixxx;
36 m_pMidiDeviceManager = midi;
37@@ -76,7 +77,7 @@
38 wreplaygain = new DlgPrefReplayGain(this, config);
39 wrecord = new DlgPrefRecord(this, config);
40 #ifdef __VINYLCONTROL__
41- wvinylcontrol = new DlgPrefVinyl(this, soundman, config);
42+ wvinylcontrol = new DlgPrefVinyl(this, pVCManager, config);
43 #else
44 wnovinylcontrol = new DlgPrefNoVinyl(this, soundman, config);
45 #endif
46@@ -139,8 +140,6 @@
47 #endif
48
49 #ifdef __VINYLCONTROL__
50- connect(wvinylcontrol, SIGNAL(refreshVCProxies()), wsound, SLOT(forceApply()));
51- connect(wvinylcontrol, SIGNAL(applySound()), wsound, SLOT(slotApply()));
52 connect(buttonBox, SIGNAL(accepted()), wvinylcontrol, SLOT(slotApply())); //It's important for this to be before the
53 //connect for wsound...
54 #endif
55
56=== modified file 'mixxx/src/dlgpreferences.h'
57--- mixxx/src/dlgpreferences.h 2011-04-16 20:03:36 +0000
58+++ mixxx/src/dlgpreferences.h 2011-04-18 08:02:27 +0000
59@@ -49,6 +49,7 @@
60 class MidiDeviceManager;
61 class SkinLoader;
62 class PlayerManager;
63+class VinylControlManager;
64
65 /**
66 *@author Tue & Ken Haste Andersen
67@@ -60,7 +61,7 @@
68 public:
69 DlgPreferences(MixxxApp *mixxx, SkinLoader* pSkinLoader, SoundManager *soundman,
70 PlayerManager* pPlayerManager, MidiDeviceManager* midi,
71- ConfigObject<ConfigValue> *config);
72+ VinylControlManager *pVCManager, ConfigObject<ConfigValue> *config);
73
74 ~DlgPreferences();
75 void createIcons();
76
77=== modified file 'mixxx/src/dlgprefsound.cpp'
78--- mixxx/src/dlgprefsound.cpp 2011-04-15 07:08:16 +0000
79+++ mixxx/src/dlgprefsound.cpp 2011-04-18 08:02:27 +0000
80@@ -117,22 +117,6 @@
81 if (!m_settingsModified && !m_forceApply) {
82 return;
83 }
84-#ifdef __VINYLCONTROL__
85- // Scratchlib sucks, throw rocks at it
86- // XXX(bkgood) HACKS DELETE THIS WHEN SCRATCHLIB GETS NUKED KTHX
87- if ((m_pConfig->getValueString(ConfigKey("[Channel1]", "vinylcontrol_vinyl_type"))
88- == MIXXX_VINYL_FINALSCRATCH ||
89- m_pConfig->getValueString(ConfigKey("[Channel2]", "vinylcontrol_vinyl_type"))
90- == MIXXX_VINYL_FINALSCRATCH)
91- &&
92- sampleRateComboBox->itemData(sampleRateComboBox->currentIndex()).toUInt()
93- != 44100) {
94- QMessageBox::warning(this, tr("Mixxx Error"),
95- tr("FinalScratch records currently only work properly with a "
96- "44100 Hz sample rate.\nThe sample rate has been reset to 44100 Hz."));
97- sampleRateComboBox->setCurrentIndex(sampleRateComboBox->findData(44100));
98- }
99-#endif
100 m_forceApply = false;
101 m_config.clearInputs();
102 m_config.clearOutputs();
103
104=== modified file 'mixxx/src/dlgprefvinyl.cpp'
105--- mixxx/src/dlgprefvinyl.cpp 2011-04-16 20:15:25 +0000
106+++ mixxx/src/dlgprefvinyl.cpp 2011-04-18 08:02:27 +0000
107@@ -23,19 +23,17 @@
108 #include <QtGui>
109 #include "dlgprefvinyl.h"
110 #include "controlobject.h"
111-#include "soundmanager.h"
112-#include "vinylcontrol.h" //For vinyl type string constants
113+#include "vinylcontrol/vinylcontrolmanager.h"
114+#include "vinylcontrol/vinylcontrol.h" //For vinyl type string constants
115 #include "controlobjectthreadmain.h"
116-#include "vinylcontrolsignalwidget.h"
117 #include "dlgprefvinyl.h"
118
119-DlgPrefVinyl::DlgPrefVinyl(QWidget * parent, SoundManager * soundman,
120+DlgPrefVinyl::DlgPrefVinyl(QWidget * parent, VinylControlManager *pVCMan,
121 ConfigObject<ConfigValue> * _config) : QWidget(parent), Ui::DlgPrefVinylDlg(),
122 m_COTMode(ControlObject::getControl(ConfigKey("[VinylControl]", "mode")))
123 {
124- m_pSoundManager = soundman;
125+ m_pVCManager = pVCMan;
126 config = _config;
127- m_dontForce = false;
128
129 setupUi(this);
130
131@@ -75,17 +73,6 @@
132 connect(applyButton, SIGNAL(clicked()), this, SLOT(slotApply()));
133 connect(VinylGain, SIGNAL(sliderReleased()), this, SLOT(VinylGainSlotApply()));
134 //connect(ComboBoxDeviceDeck1, SIGNAL(currentIndexChanged()), this, SLOT(()));
135-
136- connect(VinylGain, SIGNAL(sliderReleased()), this, SLOT(settingsChanged()));
137- connect(ComboBoxVinylType1, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
138- connect(ComboBoxVinylType2, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
139- connect(ComboBoxVinylSpeed1, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
140- connect(ComboBoxVinylSpeed2, SIGNAL(currentIndexChanged(int)), this, SLOT(settingsChanged()));
141- connect(LeadinTime, SIGNAL(textChanged(const QString&)), this, SLOT(settingsChanged()));
142- connect(NeedleSkipEnable, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged()));
143- connect(AbsoluteMode, SIGNAL(toggled(bool)), this, SLOT(settingsChanged()));
144- connect(RelativeMode, SIGNAL(toggled(bool)), this, SLOT(settingsChanged()));
145- connect(m_pSoundManager, SIGNAL(devicesSetup()), this, SLOT(settingsChanged()));
146 }
147
148 DlgPrefVinyl::~DlgPrefVinyl()
149@@ -95,7 +82,7 @@
150 /** @brief Performs any necessary actions that need to happen when the prefs dialog is opened */
151 void DlgPrefVinyl::slotShow()
152 {
153- QList<VinylControlProxy*> VCProxiesList = m_pSoundManager->getVinylControlProxies();
154+ QList<VinylControlProxy*> VCProxiesList = m_pVCManager->vinylControlProxies();
155 if (VCProxiesList.value(0) != NULL)
156 m_signalWidget1.setVinylControlProxy(VCProxiesList.value(0));
157 if (VCProxiesList.value(1) != NULL)
158@@ -119,8 +106,6 @@
159
160 void DlgPrefVinyl::slotUpdate()
161 {
162- m_dontForce = true; // otherwise all the signals fired in here will cause
163- // DlgPrefSound to call setupDevices needlessly :) -- bkgood
164 // Set vinyl control types in the comboboxes
165 int combo_index = ComboBoxVinylType1->findText(config->getValueString(ConfigKey("[Channel1]","vinylcontrol_vinyl_type")));
166 if (combo_index != -1)
167@@ -153,17 +138,26 @@
168
169 //set vinyl control gain
170 VinylGain->setValue( config->getValueString(ConfigKey("[VinylControl]","gain")).toInt());
171- m_dontForce = false;
172+
173+ QList<VinylControlProxy*> VCProxiesList = m_pVCManager->vinylControlProxies();
174+ if (VCProxiesList.value(0) != NULL) {
175+ m_signalWidget1.setVinylControlProxy(VCProxiesList.value(0));
176+ }
177+ if (VCProxiesList.value(1) != NULL) {
178+ m_signalWidget2.setVinylControlProxy(VCProxiesList.value(1));
179+ }
180+
181+ m_signalWidget1.setVinylActive(m_pVCManager->vinylInputEnabled(1));
182+ m_signalWidget2.setVinylActive(m_pVCManager->vinylInputEnabled(2));
183 }
184
185 // Update the config object with parameters from dialog
186 void DlgPrefVinyl::slotApply()
187 {
188- QString device2;
189 qDebug() << "DlgPrefVinyl::Apply";
190
191 // Lead-in time
192- QString strLeadIn = LeadinTime->text();
193+ QString strLeadIn = LeadinTime->text();
194 bool isInteger;
195 strLeadIn.toInt(&isInteger);
196 if (isInteger)
197@@ -187,6 +181,7 @@
198 config->set(ConfigKey("[VinylControl]","mode"), ConfigValue(iMode));
199 config->set(ConfigKey("[VinylControl]","needle_skip_prevention" ), ConfigValue( (int)(NeedleSkipEnable->isChecked( )) ) );
200
201+ m_pVCManager->reloadConfig();
202 slotUpdate();
203 }
204
205@@ -201,7 +196,6 @@
206 config->set(ConfigKey("[Channel2]","vinylcontrol_vinyl_type"), ConfigValue(ComboBoxVinylType2->currentText()));
207 config->set(ConfigKey("[Channel1]","vinylcontrol_speed_type"), ConfigValue(ComboBoxVinylSpeed1->currentText()));
208 config->set(ConfigKey("[Channel2]","vinylcontrol_speed_type"), ConfigValue(ComboBoxVinylSpeed2->currentText()));
209- emit(applySound());
210 }
211
212 void DlgPrefVinyl::VinylGainSlotApply()
213@@ -214,20 +208,3 @@
214 ControlObject* pControlObjectVinylControlGain = ControlObject::getControl(ConfigKey("[VinylControl]", "gain"));
215 pControlObjectVinylControlGain->set(VinylGain->value());
216 }
217-
218-void DlgPrefVinyl::settingsChanged() {
219- if (!m_dontForce) {
220- emit(refreshVCProxies());
221- }
222-
223- QList<VinylControlProxy*> VCProxiesList = m_pSoundManager->getVinylControlProxies();
224- if (VCProxiesList.value(0) != NULL) {
225- m_signalWidget1.setVinylControlProxy(VCProxiesList.value(0));
226- }
227- if (VCProxiesList.value(1) != NULL) {
228- m_signalWidget2.setVinylControlProxy(VCProxiesList.value(1));
229- }
230-
231- m_signalWidget1.setVinylActive(m_pSoundManager->hasVinylInput(0));
232- m_signalWidget2.setVinylActive(m_pSoundManager->hasVinylInput(1));
233-}
234
235=== modified file 'mixxx/src/dlgprefvinyl.h'
236--- mixxx/src/dlgprefvinyl.h 2011-04-16 20:15:56 +0000
237+++ mixxx/src/dlgprefvinyl.h 2011-04-18 08:02:27 +0000
238@@ -20,14 +20,14 @@
239
240 #include "ui_dlgprefvinyldlg.h"
241 #include "configobject.h"
242-#include "vinylcontrolsignalwidget.h"
243+#include "vinylcontrol/vinylcontrolsignalwidget.h"
244 #include "controlobjectthread.h"
245
246 class QWidget;
247 class PlayerProxy;
248 class ControlObject;
249 class ControlObjectThreadMain;
250-class SoundManager;
251+class VinylControlManager;
252
253 /**
254 *@author Stefan Langhammer
255@@ -37,7 +37,7 @@
256 class DlgPrefVinyl : public QWidget, Ui::DlgPrefVinylDlg {
257 Q_OBJECT
258 public:
259- DlgPrefVinyl(QWidget *parent, SoundManager* soundman, ConfigObject<ConfigValue> *_config);
260+ DlgPrefVinyl(QWidget *pParent, VinylControlManager *m_pVCMan, ConfigObject<ConfigValue> *_config);
261 ~DlgPrefVinyl();
262
263 public slots:
264@@ -51,11 +51,6 @@
265 void slotShow();
266
267 signals:
268- void apply();
269- void refreshVCProxies();
270- void applySound();
271-private slots:
272- void settingsChanged();
273 private:
274 VinylControlSignalWidget m_signalWidget1;
275 VinylControlSignalWidget m_signalWidget2;
276@@ -63,7 +58,7 @@
277
278 /** Pointer to player device */
279 //PlayerProxy *player;
280- SoundManager* m_pSoundManager;
281+ VinylControlManager* m_pVCManager;
282 /** Pointer to config object */
283 ConfigObject<ConfigValue> *config;
284 /** Indicates the strength of the timecode signal on each input */
285@@ -74,7 +69,6 @@
286 ControlObjectThreadMain* m_vinylControlInput2L;
287 ControlObjectThreadMain* m_vinylControlInput2R;
288 ControlObjectThread m_COTMode;
289- bool m_dontForce;
290 };
291
292 #endif
293
294=== modified file 'mixxx/src/engine/enginebuffer.cpp'
295--- mixxx/src/engine/enginebuffer.cpp 2011-04-17 02:42:45 +0000
296+++ mixxx/src/engine/enginebuffer.cpp 2011-04-18 08:02:27 +0000
297@@ -754,9 +754,9 @@
298 }
299
300 // Update indicators that are only updated after every
301- // sampleRate/UPDATE_RATE samples processed. (e.g. playposSlider,
302+ // sampleRate/kiUpdateRate samples processed. (e.g. playposSlider,
303 // rateEngine)
304- if (m_iSamplesCalculated > (m_pSampleRate->get()/UPDATE_RATE)) {
305+ if (m_iSamplesCalculated > (m_pSampleRate->get()/kiUpdateRate)) {
306 playposSlider->set(fFractionalPlaypos);
307
308 if(rate != rateEngine->get())
309
310=== modified file 'mixxx/src/engine/enginebuffer.h'
311--- mixxx/src/engine/enginebuffer.h 2011-04-17 02:42:45 +0000
312+++ mixxx/src/engine/enginebuffer.h 2011-04-18 08:02:27 +0000
313@@ -58,7 +58,7 @@
314 const int kiTempLength = 200000;
315
316 // Rate at which the playpos slider is updated (using a sample rate of 44100 Hz):
317-const int UPDATE_RATE = 10;
318+const int kiUpdateRate = 10;
319
320 // End of track mode constants
321 const int TRACK_END_MODE_STOP = 0;
322
323=== modified file 'mixxx/src/engine/vinylcontrolcontrol.cpp'
324--- mixxx/src/engine/vinylcontrolcontrol.cpp 2011-04-17 02:42:45 +0000
325+++ mixxx/src/engine/vinylcontrolcontrol.cpp 2011-04-18 08:02:27 +0000
326@@ -1,6 +1,6 @@
327 #include "engine/vinylcontrolcontrol.h"
328
329-#include "vinylcontrol.h"
330+#include "vinylcontrol/vinylcontrol.h"
331 #include "library/dao/cue.h"
332
333 VinylControlControl::VinylControlControl(const char* pGroup, ConfigObject<ConfigValue>* pConfig)
334
335=== modified file 'mixxx/src/mixxx.cpp'
336--- mixxx/src/mixxx.cpp 2011-04-16 19:50:10 +0000
337+++ mixxx/src/mixxx.cpp 2011-04-18 08:02:27 +0000
338@@ -64,6 +64,11 @@
339
340 #include "defs_version.h"
341
342+#ifdef __VINYLCONTROL__
343+#include "vinylcontrol/vinylcontrol.h"
344+#include "vinylcontrol/vinylcontrolmanager.h"
345+#endif
346+
347 #ifdef __C_METRICS__
348 #include <cmetrics.h>
349 #include "defs_mixxxcmetrics.h"
350@@ -315,6 +320,17 @@
351 AudioOutput(AudioOutput::DECK, 0, deck), m_pEngine);
352 }
353
354+#ifdef __VINYLCONTROL__
355+ m_pVCManager = new VinylControlManager(this, m_pConfig);
356+ for (unsigned int deck = 0; deck < m_pPlayerManager->numDecks(); ++deck) {
357+ m_pSoundManager->registerInput(
358+ AudioInput(AudioInput::VINYLCONTROL, 0, deck),
359+ m_pVCManager);
360+ }
361+#else
362+ m_pVCManager = NULL;
363+#endif
364+
365 //Scan the library directory.
366 m_pLibraryScanner = new LibraryScanner(m_pLibrary->getTrackCollection());
367
368@@ -372,16 +388,8 @@
369 m_pConfig->set(ConfigKey("[BPM]", "AnalyzeEntireSong"),ConfigValue(1));
370 }
371
372-#ifdef __VINYLCONTROL__
373 //ControlObject::getControl(ConfigKey("[Channel1]","TrackEndMode"))->queueFromThread(m_pConfig->getValueString(ConfigKey("[Controls]","TrackEndModeCh1")).toDouble());
374 //ControlObject::getControl(ConfigKey("[Channel2]","TrackEndMode"))->queueFromThread(m_pConfig->getValueString(ConfigKey("[Controls]","TrackEndModeCh2")).toDouble());
375- ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_enabled"))->queueFromThread(m_pConfig->getValueString(ConfigKey("[VinylControl]","enabled_ch1")).toDouble());
376- ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_enabled"))->queueFromThread(m_pConfig->getValueString(ConfigKey("[VinylControl]","enabled_ch2")).toDouble());
377- ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_mode"))->queueFromThread(m_pConfig->getValueString(ConfigKey("[VinylControl]","mode")).toDouble());
378- ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_mode"))->queueFromThread(m_pConfig->getValueString(ConfigKey("[VinylControl]","mode")).toDouble());
379- ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_cueing"))->queueFromThread(m_pConfig->getValueString(ConfigKey("[VinylControl]","cueing_ch1")).toDouble());
380- ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_cueing"))->queueFromThread(m_pConfig->getValueString(ConfigKey("[VinylControl]","cueing_ch2")).toDouble());
381-#endif
382
383 qRegisterMetaType<MidiMessage>("MidiMessage");
384 qRegisterMetaType<MidiStatusByte>("MidiStatusByte");
385@@ -394,7 +402,7 @@
386
387 // Initialize preference dialog
388 m_pPrefDlg = new DlgPreferences(this, m_pSkinLoader, m_pSoundManager, m_pPlayerManager,
389- m_pMidiDeviceManager, m_pConfig);
390+ m_pMidiDeviceManager, m_pVCManager, m_pConfig);
391 m_pPrefDlg->setHidden(true);
392
393 // Try open player device If that fails, the preference panel is opened.
394@@ -529,18 +537,18 @@
395 // Save state of End of track controls in config database
396 //m_pConfig->set(ConfigKey("[Controls]","TrackEndModeCh1"), ConfigValue((int)ControlObject::getControl(ConfigKey("[Channel1]","TrackEndMode"))->get()));
397 //m_pConfig->set(ConfigKey("[Controls]","TrackEndModeCh2"), ConfigValue((int)ControlObject::getControl(ConfigKey("[Channel2]","TrackEndMode"))->get()));
398-#ifdef __VINYLCONTROL__
399- m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch1"), ConfigValue((int)ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_enabled"))->get()));
400- m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch2"), ConfigValue((int)ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_enabled"))->get()));
401- m_pConfig->set(ConfigKey("[VinylControl]","mode"), ConfigValue((int)ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_mode"))->get()));
402- m_pConfig->set(ConfigKey("[VinylControl]","mode"), ConfigValue((int)ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_mode"))->get()));
403- m_pConfig->set(ConfigKey("[VinylControl]","cueing_ch1"), ConfigValue((int)ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_cueing"))->get()));
404- m_pConfig->set(ConfigKey("[VinylControl]","cueing_ch2"), ConfigValue((int)ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_cueing"))->get()));
405-#endif
406+
407 // SoundManager depend on Engine and Config
408 qDebug() << "delete soundmanager, " << qTime.elapsed();
409 delete m_pSoundManager;
410
411+#ifdef __VINYLCONTROL__
412+ // VinylControlManager depends on a CO the engine owns
413+ // (vinylcontrol_enabled in VinylControlControl)
414+ qDebug() << "delete vinylcontrolmanager, " << qTime.elapsed();
415+ delete m_pVCManager;
416+#endif
417+
418 // View depends on MixxxKeyboard, PlayerManager, Library
419 qDebug() << "delete view, " << qTime.elapsed();
420 delete m_pView;
421@@ -1143,7 +1151,7 @@
422 void MixxxApp::slotControlVinylControl(double toggle)
423 {
424 #ifdef __VINYLCONTROL__
425- if (tryToggleVinylControl(0)) {
426+ if (m_pVCManager->vinylInputEnabled(1)) {
427 m_pConfig->set(
428 ConfigKey("[VinylControl]", "enabled_ch1"), ConfigValue((int)toggle));
429 m_pOptionsVinylControl->setChecked((bool)toggle);
430@@ -1180,18 +1188,11 @@
431 #endif
432 }
433
434-int MixxxApp::tryToggleVinylControl(int deck)
435-{
436-#ifdef __VINYLCONTROL__
437- return m_pSoundManager->hasVinylInput(deck);
438-#endif
439-}
440-
441 void MixxxApp::slotControlVinylControl2(double toggle)
442 {
443 #ifdef __VINYLCONTROL__
444 //we just need at least 1 input (deck 1) because of single deck mode
445- if (tryToggleVinylControl(1)) {
446+ if (m_pVCManager->vinylInputEnabled(2)) {
447 m_pConfig->set(
448 ConfigKey("[VinylControl]", "enabled_ch2"), ConfigValue((int)toggle));
449 m_pOptionsVinylControl2->setChecked((bool)toggle);
450
451=== modified file 'mixxx/src/mixxx.h'
452--- mixxx/src/mixxx.h 2011-04-16 20:57:48 +0000
453+++ mixxx/src/mixxx.h 2011-04-18 08:02:27 +0000
454@@ -42,9 +42,6 @@
455 #include "controlobject.h"
456 #include "dlgpreferences.h"
457 //#include "trackplaylist.h"
458-#ifdef __VINYLCONTROL__
459-#include "vinylcontrol.h"
460-#endif
461 #include "recording/recordingmanager.h"
462
463 #ifdef __SCRIPT__
464@@ -66,6 +63,8 @@
465 class MixxxKeyboard;
466 class SkinLoader;
467
468+class VinylControlManager;
469+
470 /**
471 * This Class is the base class for Mixxx. It sets up the main
472 * window and providing a menubar.
473@@ -105,7 +104,6 @@
474 /** toggle vinyl control - Don't #ifdef this because MOC is dumb**/
475 void slotControlVinylControl(double toggle);
476 void slotCheckboxVinylControl(bool toggle);
477- int tryToggleVinylControl(int deck);
478 void slotControlVinylControl2(double toggle);
479 void slotCheckboxVinylControl2(bool toggle);
480 /** toggle recording - Don't #ifdef this because MOC is dumb**/
481@@ -168,6 +166,7 @@
482
483 ConfigObject<ConfigValue> *m_pConfig;
484
485+ VinylControlManager *m_pVCManager;
486
487 MixxxKeyboard* m_pKeyboard;
488 /** Library scanner object */
489
490=== modified file 'mixxx/src/soundmanager.cpp'
491--- mixxx/src/soundmanager.cpp 2011-04-16 15:25:20 +0000
492+++ mixxx/src/soundmanager.cpp 2011-04-18 08:02:27 +0000
493@@ -26,10 +26,6 @@
494 #include "controlobjectthreadmain.h"
495 #include "soundmanagerutil.h"
496
497-#ifdef __VINYLCONTROL__
498-#include "vinylcontrolxwax.h"
499-#endif
500-
501 /** Initializes Mixxx's audio core
502 * @param pConfig The config key table
503 * @param _master A pointer to the audio engine's mastering class.
504@@ -232,21 +228,6 @@
505 }
506 }
507 m_inputBuffers.clear();
508-
509-#ifdef __VINYLCONTROL__
510- // TODO(bkgood) see comment where these objects are created in setupDevices,
511- // this should probably be in the dtor or at least somewhere other
512- // than here.
513- while (!m_vinylControl.empty()) {
514- VinylControlProxy *vc = m_vinylControl.takeLast();
515- if (vc != NULL) {
516- delete vc;
517- }
518- //xwax has a global LUT that we need to free after we've shut down our
519- //vinyl control threads because it's not thread-safe.
520- VinylControlXwax::freeLUTs();
521- }
522-#endif
523 }
524
525 /** Closes all the devices and empties the list of devices we have. */
526@@ -372,18 +353,6 @@
527
528 // close open devices, close running vinyl control proxies
529 closeDevices();
530-#ifdef __VINYLCONTROL__
531- //Initialize vinyl control
532- // TODO(bkgood) this ought to be done in the ctor or something. Not here. Really
533- // shouldn't be any reason for these to be reinitialized every time the
534- // audio prefs are updated. Will require work in DlgPrefVinyl.
535- m_vinylControl.append(new VinylControlProxy(m_pConfig, "[Channel1]"));
536- m_vinylControl.append(new VinylControlProxy(m_pConfig, "[Channel2]"));
537- qDebug() << "Created VinylControlProxies" <<
538- m_vinylControl[0] << m_vinylControl[1];
539- registerInput(AudioInput(AudioInput::VINYLCONTROL, 0, 0), m_vinylControl[0]);
540- registerInput(AudioInput(AudioInput::VINYLCONTROL, 0, 1), m_vinylControl[1]);
541-#endif
542 foreach (SoundDevice *device, m_devices) {
543 bool isInput = false;
544 bool isOutput = false;
545@@ -471,32 +440,6 @@
546 return m_config;
547 }
548
549-#ifdef __VINYLCONTROL__
550-bool SoundManager::hasVinylInput(int deck)
551-{
552- if (deck >= m_vinylControl.length())
553- return false;
554- VinylControlProxy* vinyl_control = m_vinylControl[deck];
555-
556- bool hasInput = false;
557- QList<AudioInput> inputs = getConfig().getInputs().values();
558- foreach (AudioInput in, inputs) {
559- if (in.getType() == AudioInput::VINYLCONTROL
560- && in.getIndex() == deck) {
561- hasInput = true;
562- break;
563- }
564- }
565-
566- return vinyl_control != NULL && hasInput;
567-}
568-
569-QList<VinylControlProxy*> SoundManager::getVinylControlProxies()
570-{
571- return m_vinylControl;
572-}
573-#endif
574-
575 int SoundManager::setConfig(SoundManagerConfig config) {
576 int err = OK;
577 m_config = config;
578
579=== modified file 'mixxx/src/soundmanager.h'
580--- mixxx/src/soundmanager.h 2011-04-15 07:08:16 +0000
581+++ mixxx/src/soundmanager.h 2011-04-18 08:02:27 +0000
582@@ -21,9 +21,6 @@
583 #include "configobject.h"
584 #include "controlobject.h"
585 #include "defs.h"
586-#ifdef __VINYLCONTROL__
587-#include "vinylcontrolproxy.h"
588-#endif
589 #include "soundmanagerconfig.h"
590 #include <QTimer>
591
592@@ -59,10 +56,6 @@
593 QList<unsigned int> getSampleRates() const;
594 QList<QString> getHostAPIList() const;
595 SoundManagerConfig getConfig() const;
596-#ifdef __VINYLCONTROL__
597- bool hasVinylInput(int deck);
598- QList<VinylControlProxy*> getVinylControlProxies();
599-#endif
600 int setConfig(SoundManagerConfig config);
601 void checkConfig();
602 QHash<AudioOutput, const CSAMPLE*>
603@@ -92,9 +85,6 @@
604 QHash<AudioInput, short*> m_inputBuffers; /** Audio received from input */
605 QHash<SoundDevice*, long> m_deviceFrameCount; /** Sound card sync */
606 SoundDevice* m_pClkRefDevice; /** Sound card sync */
607-#ifdef __VINYLCONTROL__
608- QList<VinylControlProxy*> m_vinylControl;
609-#endif
610 unsigned int iNumDevicesOpenedForOutput;
611 unsigned int iNumDevicesOpenedForInput;
612 QMutex requestBufferMutex;
613
614=== added directory 'mixxx/src/vinylcontrol'
615=== renamed file 'mixxx/src/vinylcontrol.cpp' => 'mixxx/src/vinylcontrol/vinylcontrol.cpp'
616--- mixxx/src/vinylcontrol.cpp 2011-04-16 21:06:35 +0000
617+++ mixxx/src/vinylcontrol/vinylcontrol.cpp 2011-04-18 08:02:27 +0000
618@@ -1,10 +1,10 @@
619 #include "vinylcontrol.h"
620 #include "controlobjectthread.h"
621
622-VinylControl::VinylControl(ConfigObject<ConfigValue> * pConfig, const char * _group)
623+VinylControl::VinylControl(ConfigObject<ConfigValue> * pConfig, QString group)
624 {
625 m_pConfig = pConfig;
626- group = _group;
627+ m_group = group;
628 iRIAACorrection = 0;
629
630 iSampleRate = m_pConfig->getValueString(ConfigKey("[Soundcard]","Samplerate")).toULong();
631@@ -59,7 +59,7 @@
632 {
633 bIsEnabled = enable;
634 if (m_pConfig)
635- m_pConfig->set(ConfigKey(group,"vinylcontrol_enabled"), ConfigValue((int)enable));
636+ m_pConfig->set(ConfigKey(m_group,"vinylcontrol_enabled"), ConfigValue((int)enable));
637
638 enabled->slotSet(enable);
639
640
641=== renamed file 'mixxx/src/vinylcontrol.h' => 'mixxx/src/vinylcontrol/vinylcontrol.h'
642--- mixxx/src/vinylcontrol.h 2011-04-16 21:06:35 +0000
643+++ mixxx/src/vinylcontrol/vinylcontrol.h 2011-04-18 08:02:27 +0000
644@@ -1,5 +1,5 @@
645-#ifndef __VINYLCONTROL_H__
646-#define __VINYLCONTROL_H__
647+#ifndef VINYLCONTROL_H
648+#define VINYLCONTROL_H
649
650 #include <qthread.h>
651 #include "configobject.h"
652@@ -39,7 +39,7 @@
653 class VinylControl : public QThread
654 {
655 public:
656- VinylControl(ConfigObject<ConfigValue> *pConfig, const char *_group);
657+ VinylControl(ConfigObject<ConfigValue> *pConfig, QString group);
658 virtual ~VinylControl();
659 virtual void ToggleVinylControl(bool enable) = 0;
660 virtual bool isEnabled() = 0;
661@@ -56,7 +56,7 @@
662 QString strVinylType;
663 QString strVinylSpeed;
664 ConfigObject<ConfigValue> *m_pConfig; /** Pointer to config database */
665- const char* group;
666+ QString m_group;
667 ControlObjectThread *playButton; //The ControlObject used to start/stop playback of the song.
668 ControlObjectThread *playPos; //The ControlObject used to read the playback position in the song.
669 ControlObjectThread *vinylSeek; //The ControlObject used to change the playback position in the song.
670
671=== added file 'mixxx/src/vinylcontrol/vinylcontrolmanager.cpp'
672--- mixxx/src/vinylcontrol/vinylcontrolmanager.cpp 1970-01-01 00:00:00 +0000
673+++ mixxx/src/vinylcontrol/vinylcontrolmanager.cpp 2011-04-18 08:02:27 +0000
674@@ -0,0 +1,148 @@
675+/**
676+ * @file vinylcontrolmanager.cpp
677+ * @author Bill Good <bkgood@gmail.com>
678+ * @date April 15, 2011
679+ */
680+
681+#include "vinylcontrolmanager.h"
682+#include "vinylcontrolproxy.h"
683+#include "vinylcontrolxwax.h"
684+#include "soundmanager.h"
685+
686+const int kNumberOfDecks = 4; // set to 4 because it will ideally not be more
687+// or less than the number of vinyl-controlled decks but will probably be
688+// forgotten in any 2->4 deck switchover. Only real consequence is
689+// sizeof(void*)*2 bytes of wasted memory if we're only using 2 decks -bkgood
690+
691+const QString kVCProxyGroup = QString("[Channel%1]");
692+
693+VinylControlManager::VinylControlManager(QObject *pParent,
694+ ConfigObject<ConfigValue> *pConfig)
695+ : QObject(pParent)
696+ , m_pConfig(pConfig)
697+ , m_proxies(kNumberOfDecks, NULL) {
698+ // load a bunch of stuff
699+ ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_enabled"))
700+ ->queueFromThread(m_pConfig->getValueString(
701+ ConfigKey("[VinylControl]","enabled_ch1")).toDouble());
702+ ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_enabled"))
703+ ->queueFromThread(m_pConfig->getValueString(
704+ ConfigKey("[VinylControl]","enabled_ch2")).toDouble());
705+ ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_mode"))
706+ ->queueFromThread(m_pConfig->getValueString(
707+ ConfigKey("[VinylControl]","mode")).toDouble());
708+ ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_mode"))
709+ ->queueFromThread(m_pConfig->getValueString(
710+ ConfigKey("[VinylControl]","mode")).toDouble());
711+ ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_cueing"))
712+ ->queueFromThread(m_pConfig->getValueString(
713+ ConfigKey("[VinylControl]","cueing_ch1")).toDouble());
714+ ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_cueing"))
715+ ->queueFromThread(m_pConfig->getValueString(
716+ ConfigKey("[VinylControl]","cueing_ch2")).toDouble());
717+}
718+
719+VinylControlManager::~VinylControlManager() {
720+ m_proxiesLock.lockForWrite();
721+ for (int i = 0; i < m_proxies.size(); ++i) {
722+ if (m_proxies.at(i)) {
723+ delete m_proxies.at(i);
724+ m_proxies.replace(i, NULL);
725+ }
726+ }
727+ m_proxiesLock.unlock();
728+
729+ // xwax has a global LUT that we need to free after we've shut down our
730+ // vinyl control threads because it's not thread-safe.
731+ VinylControlXwax::freeLUTs();
732+
733+ // save a bunch of stuff to config
734+ m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch1"),
735+ ConfigValue((int)ControlObject::getControl(
736+ ConfigKey("[Channel1]","vinylcontrol_enabled"))->get()));
737+ m_pConfig->set(ConfigKey("[VinylControl]","enabled_ch2"),
738+ ConfigValue((int)ControlObject::getControl(
739+ ConfigKey("[Channel2]","vinylcontrol_enabled"))->get()));
740+ m_pConfig->set(ConfigKey("[VinylControl]","mode"),
741+ ConfigValue((int)ControlObject::getControl(
742+ ConfigKey("[Channel1]","vinylcontrol_mode"))->get()));
743+ m_pConfig->set(ConfigKey("[VinylControl]","mode"),
744+ ConfigValue((int)ControlObject::getControl(
745+ ConfigKey("[Channel2]","vinylcontrol_mode"))->get()));
746+ m_pConfig->set(ConfigKey("[VinylControl]","cueing_ch1"),
747+ ConfigValue((int)ControlObject::getControl(
748+ ConfigKey("[Channel1]","vinylcontrol_cueing"))->get()));
749+ m_pConfig->set(ConfigKey("[VinylControl]","cueing_ch2"),
750+ ConfigValue((int)ControlObject::getControl(
751+ ConfigKey("[Channel2]","vinylcontrol_cueing"))->get()));
752+}
753+
754+void VinylControlManager::receiveBuffer(AudioInput input,
755+ const short *pBuffer, unsigned int nFrames) {
756+ Q_ASSERT(input.getType() == AudioInput::VINYLCONTROL);
757+ if (m_proxiesLock.tryLockForRead()) {
758+ Q_ASSERT(input.getIndex() < m_proxies.size());
759+ VinylControlProxy *pProxy(m_proxies.at(input.getIndex()));
760+ Q_ASSERT(pProxy);
761+ pProxy->AnalyseSamples(pBuffer, nFrames);
762+ m_proxiesLock.unlock();
763+ }
764+}
765+
766+void VinylControlManager::onInputConnected(AudioInput input) {
767+ Q_ASSERT(input.getType() == AudioInput::VINYLCONTROL);
768+ unsigned char index = input.getIndex();
769+ VinylControlProxy *pNewVC = new VinylControlProxy(m_pConfig,
770+ kVCProxyGroup.arg(index + 1));
771+ m_proxiesLock.lockForWrite();
772+ if (index < m_proxies.size()) {
773+ if (m_proxies.at(index)) {
774+ delete m_proxies.at(index);
775+ }
776+ m_proxies.replace(index, pNewVC);
777+ } else {
778+ m_proxies.resize(index + 1);
779+ m_proxies.replace(index, pNewVC);
780+ }
781+ m_proxiesLock.unlock();
782+}
783+
784+void VinylControlManager::onInputDisconnected(AudioInput input) {
785+ Q_ASSERT(input.getType() == AudioInput::VINYLCONTROL);
786+ m_proxiesLock.lockForWrite();
787+ Q_ASSERT(input.getIndex() < m_proxies.size());
788+ Q_ASSERT(m_proxies.at(input.getIndex()));
789+
790+ delete m_proxies.at(input.getIndex());
791+ m_proxies.replace(input.getIndex(), NULL);
792+ m_proxiesLock.unlock();
793+}
794+
795+void VinylControlManager::reloadConfig() {
796+ m_proxiesLock.lockForWrite();
797+ for (int i = 0; i < m_proxies.size(); ++i) {
798+ if (!m_proxies.at(i)) continue;
799+ VinylControlProxy *pProxy = m_proxies.at(i);
800+ QString group = kVCProxyGroup.arg(i + 1);
801+ delete pProxy;
802+ pProxy = new VinylControlProxy(m_pConfig, group);
803+ m_proxies.replace(i, pProxy);
804+ }
805+ m_proxiesLock.unlock();
806+}
807+
808+QList<VinylControlProxy*> VinylControlManager::vinylControlProxies() {
809+ m_proxiesLock.lockForRead();
810+ QList<VinylControlProxy*> list(m_proxies.toList());
811+ m_proxiesLock.unlock();
812+ return list;
813+}
814+
815+bool VinylControlManager::vinylInputEnabled(int deck) {
816+ // a vinylcontrolproxy is only created if vinyl control is enabled for
817+ // a deck, so...
818+ m_proxiesLock.lockForRead();
819+ bool ret = (deck - 1) < m_proxies.size() && m_proxies[deck-1];
820+ m_proxiesLock.unlock();
821+ return ret;
822+}
823
824=== added file 'mixxx/src/vinylcontrol/vinylcontrolmanager.h'
825--- mixxx/src/vinylcontrol/vinylcontrolmanager.h 1970-01-01 00:00:00 +0000
826+++ mixxx/src/vinylcontrol/vinylcontrolmanager.h 2011-04-18 08:02:27 +0000
827@@ -0,0 +1,36 @@
828+/**
829+ * @file vinylcontrolmanager.h
830+ * @author Bill Good <bkgood@gmail.com>
831+ * @date April 15, 2011
832+ */
833+
834+#ifndef VINYLCONTROLMANAGER_H
835+#define VINYLCONTROLMANAGER_H
836+
837+#include <QtCore>
838+#include "soundmanagerutil.h"
839+#include "configobject.h"
840+
841+class VinylControlProxy;
842+class SoundManager;
843+
844+class VinylControlManager : public QObject, public AudioDestination {
845+ Q_OBJECT;
846+ public:
847+ VinylControlManager(QObject *pParent, ConfigObject<ConfigValue> *pConfig);
848+ virtual ~VinylControlManager();
849+ virtual void receiveBuffer(AudioInput input, const short *pBuffer, unsigned int nFrames);
850+ virtual void onInputConnected(AudioInput input);
851+ virtual void onInputDisconnected(AudioInput input);
852+ QList<VinylControlProxy*> vinylControlProxies();
853+ bool vinylInputEnabled(int deck);
854+ public slots:
855+ void reloadConfig();
856+ signals:
857+ private:
858+ ConfigObject<ConfigValue> *m_pConfig;
859+ QVector<VinylControlProxy*> m_proxies;
860+ QReadWriteLock m_proxiesLock;
861+};
862+
863+#endif // VINYLCONTROLMANAGER_H
864
865=== renamed file 'mixxx/src/vinylcontrolproxy.cpp' => 'mixxx/src/vinylcontrol/vinylcontrolproxy.cpp'
866--- mixxx/src/vinylcontrolproxy.cpp 2011-04-15 07:18:41 +0000
867+++ mixxx/src/vinylcontrol/vinylcontrolproxy.cpp 2011-04-18 08:02:27 +0000
868@@ -8,7 +8,7 @@
869
870 //IVinylControl *VinylControlProxy::m_pVinylControl = 0;
871
872-VinylControlProxy::VinylControlProxy(ConfigObject<ConfigValue> * pConfig, const char * _group) : VinylControl(pConfig, _group)
873+VinylControlProxy::VinylControlProxy(ConfigObject<ConfigValue> * pConfig, QString group) : VinylControl(pConfig, group)
874 {
875 QList<QString> xwax_timecodes;
876 QList<QString> scratchlib_timecodes;
877@@ -20,20 +20,20 @@
878 xwax_timecodes.push_back(MIXXX_VINYL_TRAKTORSCRATCHSIDEB);
879
880 //Figure out which type of timecoded vinyl we're using.
881- strVinylType = m_pConfig->getValueString(ConfigKey(_group,"vinylcontrol_vinyl_type"));
882+ strVinylType = m_pConfig->getValueString(ConfigKey(m_group,"vinylcontrol_vinyl_type"));
883
884 //Create the VinylControl object that matches the type of vinyl selected in the prefs...
885 if (xwax_timecodes.contains(strVinylType))
886 {
887- m_pVinylControl = new VinylControlXwax(pConfig, _group);
888+ m_pVinylControl = new VinylControlXwax(pConfig, m_group);
889 }
890 else
891 {
892 qDebug() << "VinylControlProxy: Unknown vinyl type " << strVinylType;
893 qDebug() << "Defaulting to Serato...";
894 strVinylType = MIXXX_VINYL_SERATOCV02VINYLSIDEA;
895- pConfig->set(ConfigKey(_group,"vinylcontrol_vinyl_type"), ConfigValue(MIXXX_VINYL_SERATOCV02VINYLSIDEA));
896- m_pVinylControl = new VinylControlXwax(pConfig, _group);
897+ pConfig->set(ConfigKey(m_group,"vinylcontrol_vinyl_type"), ConfigValue(MIXXX_VINYL_SERATOCV02VINYLSIDEA));
898+ m_pVinylControl = new VinylControlXwax(pConfig, m_group);
899 }
900 }
901
902@@ -116,12 +116,3 @@
903 return -1.0;
904 }
905
906-void VinylControlProxy::receiveBuffer(AudioInput input, const short* pBuffer,
907- unsigned int iNumFrames) {
908- if (input.getType() != AudioPath::VINYLCONTROL ||
909- QString("[Channel%1]").arg(input.getIndex()+1) != this->group) {
910- qDebug() << "WARNING: vinyl control proxy got a buffer for an "
911- "AudioInput it doesn't own";
912- }
913- AnalyseSamples(pBuffer, iNumFrames);
914-}
915
916=== renamed file 'mixxx/src/vinylcontrolproxy.h' => 'mixxx/src/vinylcontrol/vinylcontrolproxy.h'
917--- mixxx/src/vinylcontrolproxy.h 2011-04-16 21:07:10 +0000
918+++ mixxx/src/vinylcontrol/vinylcontrolproxy.h 2011-04-18 08:02:27 +0000
919@@ -4,12 +4,10 @@
920 #include "vinylcontrol.h"
921 #include "soundmanagerutil.h"
922
923-//#include "vinylcontrolscratchlib.h"
924-
925-class VinylControlProxy : public VinylControl, public AudioDestination
926+class VinylControlProxy : public VinylControl
927 {
928 public:
929- VinylControlProxy(ConfigObject<ConfigValue> *pConfig, const char *_group);
930+ VinylControlProxy(ConfigObject<ConfigValue> *pConfig, QString group);
931 ~VinylControlProxy();
932 bool isEnabled();
933 void AnalyseSamples(const short* samples, size_t size);
934@@ -19,7 +17,6 @@
935 float getTimecodeQuality();
936 unsigned char* getScopeBytemap();
937 float getAngle();
938- virtual void receiveBuffer(AudioInput input, const short *pBuffer, unsigned int iNumFrames);
939 protected:
940 VinylControl* m_pVinylControl; //Pointer to active VinylControl object
941 };
942
943=== renamed file 'mixxx/src/vinylcontrolsignalwidget.cpp' => 'mixxx/src/vinylcontrol/vinylcontrolsignalwidget.cpp'
944=== renamed file 'mixxx/src/vinylcontrolsignalwidget.h' => 'mixxx/src/vinylcontrol/vinylcontrolsignalwidget.h'
945=== renamed file 'mixxx/src/vinylcontrolxwax.cpp' => 'mixxx/src/vinylcontrol/vinylcontrolxwax.cpp'
946--- mixxx/src/vinylcontrolxwax.cpp 2011-04-15 07:08:16 +0000
947+++ mixxx/src/vinylcontrol/vinylcontrolxwax.cpp 2011-04-18 08:02:27 +0000
948@@ -37,7 +37,7 @@
949 bool VinylControlXwax::m_bLUTInitialized = false;
950 QMutex VinylControlXwax::s_xwaxLUTMutex;
951
952-VinylControlXwax::VinylControlXwax(ConfigObject<ConfigValue> * pConfig, const char * _group) : VinylControl(pConfig, _group)
953+VinylControlXwax::VinylControlXwax(ConfigObject<ConfigValue> * pConfig, QString group) : VinylControl(pConfig, group)
954 {
955 dOldPos = 0.0f;
956 m_samples = NULL;
957@@ -380,7 +380,7 @@
958 {
959 qDebug() << "discontinuing select mode, selecting track";
960 if (trackLoader == NULL)
961- trackLoader = new ControlObjectThread(ControlObject::getControl(ConfigKey(group,"LoadSelectedTrack")));
962+ trackLoader = new ControlObjectThread(ControlObject::getControl(ConfigKey(m_group,"LoadSelectedTrack")));
963
964 if (!trackLoader)
965 qDebug() << "ERROR: couldn't get track loading object?";
966
967=== renamed file 'mixxx/src/vinylcontrolxwax.h' => 'mixxx/src/vinylcontrol/vinylcontrolxwax.h'
968--- mixxx/src/vinylcontrolxwax.h 2011-04-16 22:32:31 +0000
969+++ mixxx/src/vinylcontrol/vinylcontrolxwax.h 2011-04-18 08:02:27 +0000
970@@ -23,7 +23,7 @@
971 class VinylControlXwax : public VinylControl
972 {
973 public:
974- VinylControlXwax(ConfigObject<ConfigValue> *pConfig, const char *_group);
975+ VinylControlXwax(ConfigObject<ConfigValue> *pConfig, QString group);
976 virtual ~VinylControlXwax();
977 void ToggleVinylControl(bool enable);
978 bool isEnabled();

Subscribers

People subscribed via source and target branches