Merge lp:~rryan/mixxx/atomic-co into lp:~mixxxdevelopers/mixxx/atomic-co
- atomic-co
- Merge into atomic-co
Status: | Merged |
---|---|
Merged at revision: | 3363 |
Proposed branch: | lp:~rryan/mixxx/atomic-co |
Merge into: | lp:~mixxxdevelopers/mixxx/atomic-co |
Diff against target: |
8460 lines (+1998/-3446) 107 files modified
mixxx/.cproject (+0/-110) mixxx/.gdbinit (+0/-26) mixxx/.project (+0/-79) mixxx/build/debian/changelog (+6/-0) mixxx/build/depends.py (+15/-10) mixxx/build/features.py (+2/-13) mixxx/build/qtcreator/mixxx.pro (+0/-10) mixxx/plugins/soundsourcem4a/SConscript (+1/-2) mixxx/res/skins/Shade1024x600-Netbook/skin.xml (+0/-16) mixxx/src/analyserbpm.cpp (+0/-102) mixxx/src/analyserbpm.h (+0/-27) mixxx/src/analyserqueue.cpp (+0/-11) mixxx/src/control/control.cpp (+132/-0) mixxx/src/control/control.h (+95/-0) mixxx/src/control/controlbehavior.cpp (+63/-0) mixxx/src/control/controlbehavior.h (+186/-0) mixxx/src/control/controlvalue.h (+44/-32) mixxx/src/controlbeat.cpp (+0/-83) mixxx/src/controlbeat.h (+0/-59) mixxx/src/controllers/controllerengine.cpp (+6/-8) mixxx/src/controllers/midi/midicontroller.cpp (+75/-70) mixxx/src/controllers/midi/midioutputhandler.cpp (+11/-18) mixxx/src/controllers/midi/midioutputhandler.h (+2/-2) mixxx/src/controllers/softtakeover.cpp (+1/-1) mixxx/src/controllinpotmeter.cpp (+5/-24) mixxx/src/controllinpotmeter.h (+1/-10) mixxx/src/controllogpotmeter.cpp (+8/-73) mixxx/src/controllogpotmeter.h (+3/-21) mixxx/src/controlnull.cpp (+0/-27) mixxx/src/controlnull.h (+0/-34) mixxx/src/controlobject.cpp (+49/-104) mixxx/src/controlobject.h (+31/-48) mixxx/src/controlobjectthread.cpp (+41/-42) mixxx/src/controlobjectthread.h (+33/-29) mixxx/src/controlobjectthreadmain.cpp (+34/-3) mixxx/src/controlobjectthreadmain.h (+9/-1) mixxx/src/controlobjectthreadwidget.cpp (+7/-38) mixxx/src/controlobjectthreadwidget.h (+4/-12) mixxx/src/controlpotmeter.cpp (+13/-43) mixxx/src/controlpotmeter.h (+5/-10) mixxx/src/controlpushbutton.cpp (+22/-55) mixxx/src/controlpushbutton.h (+1/-7) mixxx/src/controlttrotary.cpp (+9/-26) mixxx/src/controlttrotary.h (+2/-12) mixxx/src/dlgabout.cpp (+193/-6) mixxx/src/dlgbpmscheme.cpp (+0/-58) mixxx/src/dlgbpmscheme.h (+0/-38) mixxx/src/dlgbpmschemedlg.ui (+0/-184) mixxx/src/dlgprefbpm.cpp (+0/-455) mixxx/src/dlgprefbpm.h (+0/-67) mixxx/src/dlgprefbpmdlg.ui (+0/-141) mixxx/src/dlgprefeq.cpp (+4/-2) mixxx/src/dlgprefeq.h (+1/-1) mixxx/src/dlgpreferences.cpp (+1/-33) mixxx/src/dlgpreferences.h (+0/-2) mixxx/src/dlgprefrecord.cpp (+15/-17) mixxx/src/dlgprefshoutcast.h (+3/-5) mixxx/src/dlgtrackinfo.h (+9/-1) mixxx/src/encoder/encoder.cpp (+2/-15) mixxx/src/encoder/encoder.h (+9/-19) mixxx/src/encoder/encodercallback.h (+8/-25) mixxx/src/encoder/encodermp3.cpp (+80/-90) mixxx/src/encoder/encodermp3.h (+11/-25) mixxx/src/encoder/encodervorbis.cpp (+27/-41) mixxx/src/encoder/encodervorbis.h (+15/-20) mixxx/src/engine/bpmcontrol.cpp (+10/-0) mixxx/src/engine/enginebuffer.cpp (+3/-0) mixxx/src/engine/enginemaster.cpp (+8/-15) mixxx/src/engine/enginemaster.h (+4/-4) mixxx/src/engine/loopingcontrol.cpp (+10/-8) mixxx/src/engine/ratecontrol.cpp (+16/-5) mixxx/src/engine/sidechain/enginerecord.cpp (+64/-77) mixxx/src/engine/sidechain/enginerecord.h (+19/-20) mixxx/src/engine/sidechain/engineshoutcast.cpp (+86/-88) mixxx/src/engine/sidechain/engineshoutcast.h (+12/-13) mixxx/src/engine/sidechain/enginesidechain.cpp (+75/-156) mixxx/src/engine/sidechain/enginesidechain.h (+29/-39) mixxx/src/engine/sidechain/sidechainworker.h (+14/-0) mixxx/src/library/autodjfeature.cpp (+3/-2) mixxx/src/library/baseexternallibraryfeature.cpp (+2/-0) mixxx/src/library/baseplaylistfeature.cpp (+2/-2) mixxx/src/library/basesqltablemodel.cpp (+1/-1) mixxx/src/library/dao/playlistdao.cpp (+56/-17) mixxx/src/library/dao/playlistdao.h (+3/-3) mixxx/src/library/legacylibraryimporter.cpp (+2/-1) mixxx/src/library/playlistfeature.cpp (+2/-4) mixxx/src/library/playlisttablemodel.cpp (+2/-2) mixxx/src/library/setlogfeature.cpp (+6/-4) mixxx/src/main.cpp (+2/-0) mixxx/src/mixxx.cpp (+80/-285) mixxx/src/mixxx.h (+8/-4) mixxx/src/playermanager.cpp (+39/-9) mixxx/src/playermanager.h (+11/-0) mixxx/src/recording/recordingmanager.cpp (+43/-21) mixxx/src/recording/recordingmanager.h (+4/-2) mixxx/src/shoutcast/defs_shoutcast.h (+3/-0) mixxx/src/shoutcast/shoutcastmanager.cpp (+30/-0) mixxx/src/shoutcast/shoutcastmanager.h (+32/-0) mixxx/src/skin/propertybinder.cpp (+1/-2) mixxx/src/sounddeviceportaudio.cpp (+3/-2) mixxx/src/soundmanager.cpp (+2/-0) mixxx/src/test/analyserbpmtest.cpp (+0/-103) mixxx/src/vinylcontrol/vinylcontrolmanager.cpp (+10/-10) mixxx/src/waveform/renderers/waveformmarkset.cpp (+2/-2) mixxx/src/widget/wpushbutton.cpp (+2/-1) mixxx/src/widget/wtracktableview.cpp (+2/-0) mixxx/vamp-plugins/SConscript (+1/-1) |
To merge this branch: | bzr merge lp:~rryan/mixxx/atomic-co |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Schürmann | Approve | ||
Review via email: mp+163831@code.launchpad.net |
Commit message
Description of the change
RJ Skerry-Ryan (rryan) wrote : | # |
Daniel Schürmann (daschuer) wrote : | # |
Hi RJ,
Here only some edges in advanced, not a complete review.
* Since ControlObjectBase is not a base class any more, we should rename it to ControlObjectAtomic
* the name ControlNumericP
http://
* I am not sure if I like your m_pBehavior logic. It looks like you intended to make it also non blocking thread save
But I think it is not required, because only the CO owner should be allowed to set the behaviour of the CO.
It is required to change from elsewhere?
I think your solution might be not entirely save, because this check may fail:
return m_pBehavior ? m_pBehavior-
m_pBehavior may change to NULL or from NULL between the check and the use.
ControlObjectBa
* We schould check the same for
Daniel Schürmann (daschuer) wrote : | # |
.. m_defaultValue.
* I would like to get rid of sub and add. It may implies that it is an atomic operation.
* We may introduce a One reader version, instead where sub and add is save.
* The same issue may occur for all other read modify write actions inside the user code.
* We only have to decide if we verify the use by the CPU (overhead) or if we rely on the correctness of the user code?
Daniel Schürmann (daschuer) wrote : | # |
I like the idea of having a COT, which controls the value change signal for the own changes.
I am not sure if I have fully understand the new behaviour bit here are my comments:
I do not like the idea that ControlObject receives signals. For me it is not clear in which thread it lives.
And I would like to allow two QObjects in the same thread communicate with signals.
What about this:
* An Object has a COT member with set(double value);
* The COT calls set(value, this) of the CO
* The CO emits valueChanged(double value, QObject* sender) in any case
* COT is connected to this signal and remits valueChanged(double value) in case this != sender
This allows that all other QObjects will receive the valueChange signals regardless in which thread it lives.
The resend of COT is "cheap" a direct connection in any case.
Code that is resend resistant, can work with CO without COT the wrapper.
COT should be renamed to something like ControlObjectValve
RJ Skerry-Ryan (rryan) wrote : | # |
> * Since ControlObjectBase is not a base class any more, we should rename it to ControlObjectAtomic
Sounds good to me.
> * the name ControlNumericP
http://
Good point, I hadn't considered we would want uint types. ControlDoublePr
> * I am not sure if I like your m_pBehavior logic. It looks like you intended to make it also non blocking thread save But I think it is not required, because only the CO owner should be allowed to set the behaviour of the CO. It is required to change from elsewhere?
I didn't want to limit who could setBehavior(). We may want to do it from elsewhere in the future?
> I think your solution might be not entirely save, because this check may fail:
return m_pBehavior ? m_pBehavior-
m_pBehavior may change to NULL or from NULL between the check and the use.
ControlObjectBa
Oops! Good point. I'll fix that. The only reason I used QAtomicPointer was to do a fetchAndSetRela
> * We schould check the same for m_defaultValue.
In this case I think we should keep COBase for defaultValue (And in the future other Control properties like a 'disabled'). In the future (e.g. in effects) the user may be able to tweak the default value of a control that represents an effect parameter so it's possible that it would change rapidly in response to user input and be accessed at the same time by another thread.
> * I would like to get rid of sub and add. It may implies that it is an atomic operation.
We could remove them. The only use of sub/add is in RateControl at the moment. I kind of like them as part of the API but I agree it gives the impression of atomicity.
> * We may introduce a One reader version, instead where sub and add is save.
Hm, given we only found one place to use sub/add I don't know if it's worth the effort.
> * The same issue may occur for all other read modify write actions inside the user code.
Yea, ControlPotmeter for example doesn't use add()/sub() for increment/
> * We only have to decide if we verify the use by the CPU (overhead) or if we rely on the correctness of the user code?
I think a balance is good. Relying on user code to be correct too much will get us into trouble since not everyone writing user code is fully aware of all the details of the control system (a good ex...
RJ Skerry-Ryan (rryan) wrote : | # |
> I do not like the idea that ControlObject receives signals. For me it is not clear in which thread it lives.
The only signal it gets is a DirectConnection so the thread shouldn't matter.
> And I would like to allow two QObjects in the same thread communicate with signals.
Could you explain more? I don't think I get it.
> What about this:
> * An Object has a COT member with set(double value);
> * The COT calls set(value, this) of the CO
> * The CO emits valueChanged(double value, QObject* sender) in any case
> * COT is connected to this signal and remits valueChanged(double value) in case this != sender
> This allows that all other QObjects will receive the valueChange signals regardless in which thread it lives.
> The resend of COT is "cheap" a direct connection in any case.
Yea, I also consider DirectConnection to be cheap performance-wise.
Basically, what I've implemented is almost exactly what you're describing except it has some additional benefits. Think of it like this:
* I have renamed ControlObject to ControlNumericP
* I pulled out all the logic that was previously specialized by sub-classing ControlObject into ControlBehavior.
* All of the previous ControlObject classes (CO, ControlPotmeter, ControlPushButton, etc.) have now been converted into ControlObjectTh
> Code that is resend resistant, can work with CO without COT the wrapper.
No code in Mixxx has been consciously written to be resend resistant except the slots that intentionally listen to both valueChanged and valueChangedFro
The benefits are:
* Separating the behavior of a control from its type. In the future when we have multiple control types that you can lookup it will be handy to be able to represent the behavior separately from the plumbing of the values. It could also allow injection of logic into a control from outside. For example, if you wanted to make a custom control that only allowed set() under a certain circumstance, you could sub-class a behavior to describe the logic you desire and then set your custom behavior on your control.
* No more master/slave relationship between CO and COT. The reason it was this way was because the CO system was designed to only be used in the engine. Today controls are defined and used everywhere in Mixxx and it's really more of a shared key-value store than it is a way to communicate with the engine. Plus, we have to deal with ugly things like NULL-ifying our pointer to the CO when it is deleted in the COT and every time you want to create a COT, you have to call ControlObject:
* This will benefit the engine-
Owen Williams (ywwg) wrote : | # |
How much rewriting is this going to require, such as for my master_sync branch which has a lot of controlobject fiddliness?
Daniel Schürmann (daschuer) wrote : | # |
> How much rewriting is this going to require, such as for my master_sync branch
> which has a lot of controlobject fiddliness?
This will be definitely a problem if we go to much a head with this branch.
I think in the current state there is some assembly line work required but since a controlObject is still a control Object there should be no logic changes required.
So I think we should try to finish and merge a branch soon, which has proved that ControlObjectBase is working.
RJ Skerry-Ryan (rryan) wrote : | # |
> How much rewriting is this going to require, such as for my master_sync branch which has a lot of controlobject fiddliness?
For this branch, if we keep the separation between valueChanged and valueChangedFro
For engine-
Daniel Schürmann (daschuer) wrote : | # |
> Maybe behaviors should be templated to save common logic across
> the value types?
Yes, we have only to deal with the not temple-atable Qt signals
> > * I would like to get rid of sub and add. It may implies that it is an
> atomic operation.
>
> We could remove them. The only use of sub/add is in RateControl at the moment.
> I kind of like them as part of the API but I agree it gives the impression of
> atomicity.
OK then, lets remove them
> > * The same issue may occur for all other read modify write actions inside
> the user code.
>
> Yea, ControlPotmeter for example doesn't use add()/sub() for
> increment/
> extend the COBase API to include add/sub? That's a little odd because COBase
> isn't just for numeric types. It could allow you to implement
> operator+/operator- on a custom type if you want to atomically do something to
> it. Or in the future we could use c++11 lambdas and pass a lambda into COBase
> that is be used to mutate the value.
Yes, we can implement an lockfee "read modify write" in the way ARM did it:
* Watch the current value
* Add or Sub a value
* Check the if the current value was changed in the meanwhile
* If Yes, retry.
I will try it out.
- 3360. By Daniel Schürmann
-
merged rollback -r 3360 lp:~rryan/mixxx/atomic-co
- 3361. By Daniel Schürmann
-
set cReaderSlotCnt = std::numeric_
limits< int>::max( ) - 3362. By Daniel Schürmann
-
added alignement keywords
Daniel Schürmann (daschuer) wrote : | # |
Played around with add and sub and I finaly came to the conclusion to remove it, in vafour of clean code.
It is only used once and it is fully save, if there is only one writer.
RJ Skerry-Ryan (rryan) wrote : | # |
> COT should be renamed to something like ControlObjectValve
I'm up for making broad changes like this in the future but to be kind to every currently open branch author we should not rename either CO/COT/COTM/COTW until there are fewer major open branches.
RJ Skerry-Ryan (rryan) wrote : | # |
> Played around with add and sub and I finaly came to the conclusion to remove it, in vafour of clean code.
> It is only used once and it is fully save, if there is only one writer.
Ok -- I'll do that in this branch.
RJ Skerry-Ryan (rryan) wrote : | # |
> * the name ControlNumericP
Fixed
> I think your solution might be not entirely save, because this check may fail:
return m_pBehavior ? m_pBehavior-
Fixed
> Played around with add and sub and I finaly came to the conclusion to remove it, in vafour of clean code.
Fixed
RJ Skerry-Ryan (rryan) wrote : | # |
I've re-reviewed the whole branch and merged with lp:~mixxxdevelopers/mixxx/atomic-co and think it's ready to merge into lp:mixxx. I can't wait to get this tested by bleeding-edgers. :)
Sean M. Pappalardo (pegasus-renegadetech) wrote : | # |
"the name ControlNumericP
What happened to using QVariant?
Daniel Schürmann (daschuer) wrote : | # |
I think QVariant is not suitable for our approach. Because I don't want to deal with type conversion inside of Mixxx.
I have planed to introduce the following types:
double (legacy) for higest accuracy
uint32_t, for fast access, and bool values
uint8_t[4], for routing Midi Messages
QString
These types should be modifiable by a common Script API using QScriptValue.
So we have the benefit of the typeless java script code but without performance overhead of QVariant.
http://
Sean M. Pappalardo (pegasus-renegadetech) wrote : | # |
Thanks, Daniel. That makes sense and it doesn't look to be too hard to add more types in the future if we need them.
Other comments/questions I have as I read through the changes:
* Before you get too far along, shouldn't the "Control" class be called "MixxxControl" or "InternalControl" to differentiate it from other types of controls, like external hardware ones? This will be especially important to avoid confusion if we plan to directly expose these to controller scripts.
* controlbehavior.h: don't the definitions of many of the classes have a bit too much code to have it all in the .h file?
* controlbehavior.h: hard-coding max and minPosition will be problematic if in the future we want to support controllers with 14-bit controls (spread across two messages) without scripting.
* controlvalue.h: what exactly does "sacrifice perfect consistency" mean? That occasionally a read value may be out of date? How likely is that to happen and can we somehow keep track of when it does incase we start seeing strange problems elsewhere as a result?
* midicontroller.cpp, line 270 (QString message): Come on, now. You actually made it harder to read. :)
* various places: isn't "getMidiValue" clearer than "getValueToMidi" since the output is a MIDI-scaled (0..127) value?
* controllinpotme
Sean M. Pappalardo (pegasus-renegadetech) wrote : | # |
Oh, isn't a straight 1-bit bool better than a uint32_t for boolean values?
Daniel Schürmann (daschuer) wrote : | # |
> Oh, isn't a straight 1-bit bool better than a uint32_t for boolean values?
Just noticed: We should introduce an int32_t control Object, not unsigned.
I do not like to have bool ControlObjects, because they have no value for invalid.
There is no performance overhead to store boolean into an int32_t.
It is only a question of min and max value of an control o0bject.
From the script, using boolean is fine.
RJ Skerry-Ryan (rryan) wrote : | # |
Hey Sean,
> * Before you get too far along, shouldn't the "Control" class be called "MixxxControl" or "InternalControl" to differentiate it from other types of controls, like external hardware ones? This will be especially important to avoid confusion if we plan to directly expose these to controller scripts.
MixxxControl is just as redundant as ControlObject. Control is much shorter to type. Controller scripts already call these control (getControl/
> * controlbehavior.h: don't the definitions of many of the classes have a bit too much code to have it all in the .h file?
Probably a good point. I was hoping to promote inline-ability but since it's all virtual that's a lost cause anyway.
> * controlbehavior.h: hard-coding max and minPosition will be problematic if in the future we want to support controllers with 14-bit controls (spread across two messages) without scripting.
This is all copy-pasta from the various Control* implementations. The big bug with Mixxx's control system has always been hard-coding the limits of parameter space to be 0-127 to match with MIDI. I aim to change that in the future, not in this branch. Parameter space should be 0-1 always.
> * controlvalue.h: what exactly does "sacrifice perfect consistency" mean? That occasionally a read value may be out of date? How likely is that to happen and can we somehow keep track of when it does incase we start seeing strange problems elsewhere as a result?
Yep, that's right. See the discussion on the ~mixxxdeveloper
> * midicontroller.cpp, line 270 (QString message): Come on, now. You actually made it harder to read. :)
*shrug* all of this MIDI message string formatting probably belongs in a utility library anyway like src/controllers
> * various places: isn't "getMidiValue" clearer than "getValueToMidi" since the output is a MIDI-scaled (0..127) value?
This full function name could be written as getValueToMidiP
> * controllinpotme
Yea, unless you want to write a custom behavior this is always going to be an implementation detail. The reason that exists is that the control itself might be located in a place where it is not ok to malloc/free (e.g. the engine callback) so it is the caller of setBehavior's job to manage the destruction of the behavior (e.g. by passing the pointer into a FIFO that is read from by a garbage cleanup thread)...
Sean M. Pappalardo (pegasus-renegadetech) wrote : | # |
"There should just be one single parameter space for controls (instead of two parameter spaces, MIDI parameters and widget parameters) and the MIDI subsystem should do the translation to/from raw MIDI values within the controller MIDI subsystem."
For the record, I completely agree. (This was one thing that annoyed me during the controller subsystem rewrite, and it remains responsible for inconsistencies between straight XML-mapped controls and those set from script as well as code duplication to minimize them.)
RJ Skerry-Ryan (rryan) wrote : | # |
> "the name ControlNumericP
> What happened to using QVariant?
I think we should still make a QVariant control so that things like scripts can pass around custom values without recompiling the Mixxx binary to add a new control type. We can also make a QVariant-based wrapper around controls for insertion into the controller engine. I agree w/ Daniel that it doesn't make sense to sacrifice the performance in areas where we know the type we will always use for the control.
> > Oh, isn't a straight 1-bit bool better than a uint32_t for boolean values?
> Just noticed: We should introduce an int32_t control Object, not unsigned.
> I do not like to have bool ControlObjects, because they have no value for invalid.
> There is no performance overhead to store boolean into an int32_t.
> It is only a question of min and max value of an control o0bject.
> From the script, using boolean is fine.
Daniel -- this is part of why your ControlValueAtomic really excites me. One thing that has always been a huge hack in Mixxx is co-opting the value space of a control to represent a disabled state or invalid value. We can just add these as properties of the control outside of its value. This is Control 2.0 stuff we have been talking about for a long time -- finally being able to make the GUI respond to a control being disconnected/
And if we did that I think it would be fine to make a boolean control -- the API would be much nicer than what we do today to encode a bool in a double by always checking for v != 0.
RJ Skerry-Ryan (rryan) wrote : | # |
> For the record, I completely agree. (This was one thing that annoyed me during the controller subsystem rewrite, and it remains responsible for inconsistencies between straight XML-mapped controls and those set from script as well as code duplication to minimize them.)
Yea, it's been this way since Mixxx 1.0 and it's a huge hack.
If we converted everything to have one parameter space then I think every control should have a setParameter(
Sean M. Pappalardo (pegasus-renegadetech) wrote : | # |
I also fully agree on both points, RJ.
Sean M. Pappalardo (pegasus-renegadetech) wrote : | # |
> co-opting the value space of a control to represent a disabled state or invalid value
See the "scratch" CO where 0=disabled, but 1=play normal speed. Ugh. That's why I had to make a "scratch2" with a separate "scratch2_enabled" CO.
RJ Skerry-Ryan (rryan) wrote : | # |
Barring strenuous objection, I'll go ahead and merge this. Daniel, do you agree this in a merge-worthy state?
Daniel Schürmann (daschuer) wrote : | # |
Hi RJ,
Yes, I will merge it into lp:~mixxxdevelopers/mixxx/atomic-co now.
But I have not entirely reviewed and test it for merge into trunk.
I think I have not fully understand your COT changes yet so I have some code read todo.
---
the "scratch2" and "scratch2_enabled" think is definitely a subject for change in near future.
But there might be race conditions if we handle the scratch2_enabled like a property. For me it is a part of the atomic info scratch2 itself. If we introduce a int type control object we can easily reserve on value for invalid
eg -100 .. 100 + 0x7fffffff = invalid. A bool becomes 0 .. 1 + 0x7fffffff = invalid;
Or we can introduce a bitfield struct like this
struct {
int value : 31;
int invalid : 1;
}
Or if we don't mind using the ring implementation of ControlValueAtomic:
struct {
double value;
bool invalid;
}
In this way we never have an invalid flag on a valid value or vice versa.
RJ Skerry-Ryan (rryan) wrote : | # |
In that case, let's merge to lp:mixxx. Owen is waiting on this to get
master-sync merged. There will be logic issues we run into where parts of
Mixxx have not expected the CO and COT value to be flattened but we will
have to fix those as we come to them. The sooner we can get trunk testers
trying it out the better.
On Thu, May 16, 2013 at 4:48 PM, Daniel Schürmann <email address hidden>wrote:
> Review: Approve
>
> Hi RJ,
>
> Yes, I will merge it into lp:~mixxxdevelopers/mixxx/atomic-co now.
>
> But I have not entirely reviewed and test it for merge into trunk.
>
> I think I have not fully understand your COT changes yet so I have some
> code read todo.
>
> ---
>
> the "scratch2" and "scratch2_enabled" think is definitely a subject for
> change in near future.
> But there might be race conditions if we handle the scratch2_enabled like
> a property. For me it is a part of the atomic info scratch2 itself. If we
> introduce a int type control object we can easily reserve on value for
> invalid
> eg -100 .. 100 + 0x7fffffff = invalid. A bool becomes 0 .. 1 + 0x7fffffff
> = invalid;
> Or we can introduce a bitfield struct like this
> struct {
> int value : 31;
> int invalid : 1;
> }
> Or if we don't mind using the ring implementation of ControlValueAtomic:
> struct {
> double value;
> bool invalid;
> }
>
> In this way we never have an invalid flag on a valid value or vice versa.
>
>
>
> --
> https:/
> You are the owner of lp:~rryan/mixxx/atomic-co.
>
- 3363. By Daniel Schürmann
-
merged from lp:~rryan/mixxx/atomic-co
Daniel Schürmann (daschuer) wrote : | # |
OK, I will be finished today :-)
Preview Diff
1 | === removed file 'mixxx/.cproject' |
2 | --- mixxx/.cproject 2013-03-13 21:41:26 +0000 |
3 | +++ mixxx/.cproject 1970-01-01 00:00:00 +0000 |
4 | @@ -1,110 +0,0 @@ |
5 | -<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
6 | -<?fileVersion 4.0.0?> |
7 | - |
8 | -<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage"> |
9 | - <storageModule moduleId="org.eclipse.cdt.core.settings"> |
10 | - <cconfiguration id="0.1101443865"> |
11 | - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.1101443865" moduleId="org.eclipse.cdt.core.settings" name="Default"> |
12 | - <externalSettings/> |
13 | - <extensions> |
14 | - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> |
15 | - <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
16 | - <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> |
17 | - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
18 | - <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
19 | - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
20 | - </extensions> |
21 | - </storageModule> |
22 | - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> |
23 | - <configuration artifactName="mixxx" buildProperties="" description="" id="0.1101443865" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg"> |
24 | - <folderInfo id="0.1101443865." name="/" resourcePath=""> |
25 | - <toolChain id="cdt.managedbuild.toolchain.gnu.base.584041307" name="Linux GCC" resourceTypeBasedDiscovery="false" superClass="cdt.managedbuild.toolchain.gnu.base"> |
26 | - <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.351911640" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/> |
27 | - <builder arguments="-j2 clementine=0" cleanBuildTarget="-c" command="scons" id="cdt.managedbuild.target.gnu.builder.base.2000599252" incrementalBuildTarget="" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/> |
28 | - <tool id="cdt.managedbuild.tool.gnu.archiver.base.1227507869" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> |
29 | - <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.919897767" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base"> |
30 | - <option id="gnu.cpp.compiler.option.include.paths.2035064794" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath"> |
31 | - <listOptionValue builtIn="false" value="/usr/include/qt4"/> |
32 | - <listOptionValue builtIn="false" value="/usr/include/qt4/Qt"/> |
33 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtCore"/> |
34 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtGui"/> |
35 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtOpenGL"/> |
36 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtXml"/> |
37 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtSvg"/> |
38 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtSql"/> |
39 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtScript"/> |
40 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtXmlPatterns"/> |
41 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtNetwork"/> |
42 | - <listOptionValue builtIn="false" value="/usr/include/qt4/QtWebKit"/> |
43 | - <listOptionValue builtIn="false" value="/usr/include/"/> |
44 | - <listOptionValue builtIn="false" value="/usr/include/c++/4.5"/> |
45 | - </option> |
46 | - <option id="gnu.cpp.compiler.option.preprocessor.def.2028780733" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols"> |
47 | - <listOptionValue builtIn="false" value=""offsetof(Itdb_Track, artist)=1""/> |
48 | - </option> |
49 | - <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1034465664" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> |
50 | - </tool> |
51 | - <tool id="cdt.managedbuild.tool.gnu.c.compiler.base.36640467" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base"> |
52 | - <option id="gnu.c.compiler.option.preprocessor.def.symbols.293455491" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols"> |
53 | - <listOptionValue builtIn="false" value=""offsetof(Itdb_Track, artist)=1""/> |
54 | - </option> |
55 | - <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1672612692" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> |
56 | - </tool> |
57 | - <tool id="cdt.managedbuild.tool.gnu.c.linker.base.1647233207" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/> |
58 | - <tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.316845026" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base"> |
59 | - <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.654332197" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> |
60 | - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> |
61 | - <additionalInput kind="additionalinput" paths="$(LIBS)"/> |
62 | - </inputType> |
63 | - </tool> |
64 | - <tool id="cdt.managedbuild.tool.gnu.assembler.base.1421936031" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base"> |
65 | - <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1129083033" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> |
66 | - </tool> |
67 | - </toolChain> |
68 | - </folderInfo> |
69 | - </configuration> |
70 | - </storageModule> |
71 | - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> |
72 | - <storageModule moduleId="org.eclipse.cdt.core.language.mapping"/> |
73 | - </cconfiguration> |
74 | - </storageModule> |
75 | - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> |
76 | - <project id="mixxx.null.1175989019" name="mixxx"/> |
77 | - </storageModule> |
78 | - <storageModule moduleId="refreshScope" versionNumber="1"> |
79 | - <resource resourceType="PROJECT" workspacePath="/mixxx"/> |
80 | - </storageModule> |
81 | - <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/> |
82 | - <storageModule moduleId="scannerConfiguration"> |
83 | - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> |
84 | - <scannerConfigBuildInfo instanceId="0.1101443865;0.1101443865.;cdt.managedbuild.tool.gnu.c.compiler.base.36640467;cdt.managedbuild.tool.gnu.c.compiler.input.1672612692"> |
85 | - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"/> |
86 | - </scannerConfigBuildInfo> |
87 | - <scannerConfigBuildInfo instanceId="0.1101443865;0.1101443865.;cdt.managedbuild.tool.gnu.cpp.compiler.base.919897767;cdt.managedbuild.tool.gnu.cpp.compiler.input.1034465664"> |
88 | - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"/> |
89 | - </scannerConfigBuildInfo> |
90 | - <scannerConfigBuildInfo instanceId="0.1101443865"> |
91 | - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/> |
92 | - <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"> |
93 | - <buildOutputProvider> |
94 | - <openAction enabled="true" filePath="/home/daniel/workspace/.metadata/.plugins/org.eclipse.cdt.ui/mixxx.build.log"/> |
95 | - <parser enabled="true"/> |
96 | - </buildOutputProvider> |
97 | - <scannerInfoProvider id="specsFile"> |
98 | - <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="g++" useDefault="true"/> |
99 | - <parser enabled="true"/> |
100 | - </scannerInfoProvider> |
101 | - </profile> |
102 | - <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"> |
103 | - <buildOutputProvider> |
104 | - <openAction enabled="true" filePath="/home/daniel/workspace/.metadata/.plugins/org.eclipse.cdt.ui/mixxx.build.log"/> |
105 | - <parser enabled="true"/> |
106 | - </buildOutputProvider> |
107 | - <scannerInfoProvider id="makefileGenerator"> |
108 | - <runAction arguments="-E -P -v -dD" command="" useDefault="true"/> |
109 | - <parser enabled="true"/> |
110 | - </scannerInfoProvider> |
111 | - </profile> |
112 | - </scannerConfigBuildInfo> |
113 | - </storageModule> |
114 | -</cproject> |
115 | |
116 | === removed file 'mixxx/.gdbinit' |
117 | --- mixxx/.gdbinit 2013-03-13 21:41:26 +0000 |
118 | +++ mixxx/.gdbinit 1970-01-01 00:00:00 +0000 |
119 | @@ -1,26 +0,0 @@ |
120 | -dir ~/workspace/qt/src/corelib |
121 | -dir ~/workspace/qt/src/corelib/io |
122 | -dir ~/workspace/qt/src/gui |
123 | -dir ~/workspace/qt/src/gui/image |
124 | -dir ~/workspace/qt/src/gui/kernel |
125 | -dir ~/workspace/qt/src/network |
126 | -dir ~/workspace/qt/src/sql |
127 | -dir ~/workspace/qt/src/sql/drivers/sqlit |
128 | -dir ~/workspace/qt/src/opengl |
129 | -dir ~/workspace/sqlite/sqlite3-3.7.4 |
130 | -dir ~/workspace/daschuer-mixxx-clementine/src |
131 | -dir ~/workspace/daschuer-mixxx-clementine/src/core |
132 | -dir ~/workspace/daschuer-mixxx-clementine/ext |
133 | -dir ~/workspace/daschuer-mixxx-clementine/3rdparty |
134 | - |
135 | - |
136 | -python |
137 | -import sys |
138 | - |
139 | -sys.path.insert(0, '/home/daniel/workspace') |
140 | -from qt4 import register_qt4_printers |
141 | -register_qt4_printers (None) |
142 | -end |
143 | -set print pretty 1 |
144 | -set charset UTF-8 |
145 | - |
146 | |
147 | === removed file 'mixxx/.project' |
148 | --- mixxx/.project 2013-03-13 21:41:26 +0000 |
149 | +++ mixxx/.project 1970-01-01 00:00:00 +0000 |
150 | @@ -1,79 +0,0 @@ |
151 | -<?xml version="1.0" encoding="UTF-8"?> |
152 | -<projectDescription> |
153 | - <name>mixxxco</name> |
154 | - <comment></comment> |
155 | - <projects> |
156 | - </projects> |
157 | - <buildSpec> |
158 | - <buildCommand> |
159 | - <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> |
160 | - <triggers>clean,full,incremental,</triggers> |
161 | - <arguments> |
162 | - <dictionary> |
163 | - <key>?name?</key> |
164 | - <value></value> |
165 | - </dictionary> |
166 | - <dictionary> |
167 | - <key>org.eclipse.cdt.make.core.append_environment</key> |
168 | - <value>true</value> |
169 | - </dictionary> |
170 | - <dictionary> |
171 | - <key>org.eclipse.cdt.make.core.autoBuildTarget</key> |
172 | - <value>all</value> |
173 | - </dictionary> |
174 | - <dictionary> |
175 | - <key>org.eclipse.cdt.make.core.buildArguments</key> |
176 | - <value>-j2 clementine=0</value> |
177 | - </dictionary> |
178 | - <dictionary> |
179 | - <key>org.eclipse.cdt.make.core.buildCommand</key> |
180 | - <value>scons</value> |
181 | - </dictionary> |
182 | - <dictionary> |
183 | - <key>org.eclipse.cdt.make.core.cleanBuildTarget</key> |
184 | - <value>-c</value> |
185 | - </dictionary> |
186 | - <dictionary> |
187 | - <key>org.eclipse.cdt.make.core.contents</key> |
188 | - <value>org.eclipse.cdt.make.core.activeConfigSettings</value> |
189 | - </dictionary> |
190 | - <dictionary> |
191 | - <key>org.eclipse.cdt.make.core.enableAutoBuild</key> |
192 | - <value>false</value> |
193 | - </dictionary> |
194 | - <dictionary> |
195 | - <key>org.eclipse.cdt.make.core.enableCleanBuild</key> |
196 | - <value>true</value> |
197 | - </dictionary> |
198 | - <dictionary> |
199 | - <key>org.eclipse.cdt.make.core.enableFullBuild</key> |
200 | - <value>true</value> |
201 | - </dictionary> |
202 | - <dictionary> |
203 | - <key>org.eclipse.cdt.make.core.fullBuildTarget</key> |
204 | - <value></value> |
205 | - </dictionary> |
206 | - <dictionary> |
207 | - <key>org.eclipse.cdt.make.core.stopOnError</key> |
208 | - <value>true</value> |
209 | - </dictionary> |
210 | - <dictionary> |
211 | - <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key> |
212 | - <value>false</value> |
213 | - </dictionary> |
214 | - </arguments> |
215 | - </buildCommand> |
216 | - <buildCommand> |
217 | - <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> |
218 | - <triggers>full,incremental,</triggers> |
219 | - <arguments> |
220 | - </arguments> |
221 | - </buildCommand> |
222 | - </buildSpec> |
223 | - <natures> |
224 | - <nature>org.eclipse.cdt.core.cnature</nature> |
225 | - <nature>org.eclipse.cdt.core.ccnature</nature> |
226 | - <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> |
227 | - <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> |
228 | - </natures> |
229 | -</projectDescription> |
230 | |
231 | === modified file 'mixxx/Mixxx-Manual.pdf' |
232 | Binary files mixxx/Mixxx-Manual.pdf 2011-12-23 22:25:23 +0000 and mixxx/Mixxx-Manual.pdf 2013-05-16 01:44:29 +0000 differ |
233 | === modified file 'mixxx/build/debian/changelog' |
234 | --- mixxx/build/debian/changelog 2012-06-21 19:43:01 +0000 |
235 | +++ mixxx/build/debian/changelog 2013-05-16 01:44:29 +0000 |
236 | @@ -1,3 +1,9 @@ |
237 | +mixxx (1.11.0-0ubuntu1) lucid; urgency=low |
238 | + |
239 | + * New upstream release. |
240 | + |
241 | + -- RJ Ryan <rryan@mixxx.org> Thu, 09 May 2013 01:19:27 -0400 |
242 | + |
243 | mixxx (1.11.0~beta1-0ubuntu1) lucid; urgency=low |
244 | |
245 | * New upstream beta release |
246 | |
247 | === modified file 'mixxx/build/depends.py' |
248 | --- mixxx/build/depends.py 2013-05-11 22:59:25 +0000 |
249 | +++ mixxx/build/depends.py 2013-05-16 01:44:29 +0000 |
250 | @@ -113,6 +113,14 @@ |
251 | if not conf.CheckLib(libs): |
252 | raise Exception('Did not find libogg.a, libogg.lib, or the libogg development headers') |
253 | |
254 | + # libvorbisenc only exists on Linux, OSX and mingw32 on Windows. On |
255 | + # Windows with MSVS it is included in vorbisfile.dll. libvorbis and |
256 | + # libogg are included from build.py so don't add here. |
257 | + if not build.platform_is_windows or build.toolchain_is_gnu: |
258 | + vorbisenc_found = conf.CheckLib(['libvorbisenc', 'vorbisenc']) |
259 | + if not vorbisenc_found: |
260 | + raise Exception('Did not find libvorbisenc.a, libvorbisenc.lib, or the libvorbisenc development headers.') |
261 | + |
262 | def sources(self, build): |
263 | return ['soundsourceoggvorbis.cpp'] |
264 | |
265 | @@ -412,18 +420,18 @@ |
266 | sources = ["mixxxkeyboard.cpp", |
267 | |
268 | "configobject.cpp", |
269 | + "control/control.cpp", |
270 | + "control/controlbehavior.cpp", |
271 | "controlobjectthread.cpp", |
272 | "controlobjectthreadwidget.cpp", |
273 | "controlobjectthreadmain.cpp", |
274 | "controlevent.cpp", |
275 | "controllogpotmeter.cpp", |
276 | "controlobject.cpp", |
277 | - "controlnull.cpp", |
278 | "controlpotmeter.cpp", |
279 | "controllinpotmeter.cpp", |
280 | "controlpushbutton.cpp", |
281 | "controlttrotary.cpp", |
282 | - "controlbeat.cpp", |
283 | |
284 | "dlgpreferences.cpp", |
285 | "dlgprefsound.cpp", |
286 | @@ -434,10 +442,8 @@ |
287 | "controllers/dlgprefnocontrollers.cpp", |
288 | "dlgprefplaylist.cpp", |
289 | "dlgprefcontrols.cpp", |
290 | - "dlgprefbpm.cpp", |
291 | "dlgprefreplaygain.cpp", |
292 | "dlgprefnovinyl.cpp", |
293 | - "dlgbpmscheme.cpp", |
294 | "dlgabout.cpp", |
295 | "dlgprefeq.cpp", |
296 | "dlgprefcrossfader.cpp", |
297 | @@ -465,7 +471,7 @@ |
298 | "engine/engineflanger.cpp", |
299 | "engine/enginevumeter.cpp", |
300 | "engine/enginevinylsoundemu.cpp", |
301 | - "engine/enginesidechain.cpp", |
302 | + "engine/sidechain/enginesidechain.cpp", |
303 | "engine/enginefilterbutterworth8.cpp", |
304 | "engine/enginexfader.cpp", |
305 | "engine/enginemicrophone.cpp", |
306 | @@ -485,7 +491,6 @@ |
307 | |
308 | "analyserrg.cpp", |
309 | "analyserqueue.cpp", |
310 | - "analyserbpm.cpp", |
311 | "analyserwaveform.cpp", |
312 | |
313 | "controllers/controller.cpp", |
314 | @@ -577,6 +582,7 @@ |
315 | "library/recording/recordingfeature.cpp", |
316 | "dlgrecording.cpp", |
317 | "recording/recordingmanager.cpp", |
318 | + "engine/sidechain/enginerecord.cpp", |
319 | |
320 | # External Library Features |
321 | "library/baseexternallibraryfeature.cpp", |
322 | @@ -698,8 +704,9 @@ |
323 | "dlgprefrecord.cpp", |
324 | "playerinfo.cpp", |
325 | |
326 | - "recording/enginerecord.cpp", |
327 | - "recording/encoder.cpp", |
328 | + "encoder/encoder.cpp", |
329 | + "encoder/encodermp3.cpp", |
330 | + "encoder/encodervorbis.cpp", |
331 | |
332 | "segmentation.cpp", |
333 | "tapfilter.cpp", |
334 | @@ -743,10 +750,8 @@ |
335 | build.env.Uic4('dlgprefcontrolsdlg.ui') |
336 | build.env.Uic4('dlgprefeqdlg.ui') |
337 | build.env.Uic4('dlgprefcrossfaderdlg.ui') |
338 | - build.env.Uic4('dlgprefbpmdlg.ui') |
339 | build.env.Uic4('dlgprefreplaygaindlg.ui') |
340 | build.env.Uic4('dlgprefbeatsdlg.ui') |
341 | - build.env.Uic4('dlgbpmschemedlg.ui') |
342 | # build.env.Uic4('dlgbpmtapdlg.ui') |
343 | build.env.Uic4('dlgprefvinyldlg.ui') |
344 | build.env.Uic4('dlgprefnovinyldlg.ui') |
345 | |
346 | === modified file 'mixxx/build/features.py' |
347 | --- mixxx/build/features.py 2013-05-01 20:29:44 +0000 |
348 | +++ mixxx/build/features.py 2013-05-16 01:44:29 +0000 |
349 | @@ -453,8 +453,6 @@ |
350 | build.env.Append(CPPPATH=[self.INTERNAL_VAMP_PATH]) |
351 | self.INTERNAL_LINK = True |
352 | |
353 | - build.env.Append(CPPDEFINES = '__VAMP__') |
354 | - |
355 | # Needed on Linux at least. Maybe needed elsewhere? |
356 | if build.platform_is_linux: |
357 | # Optionally link libdl and libX11. Required for some distros. |
358 | @@ -802,14 +800,6 @@ |
359 | if not libshout_found: |
360 | raise Exception('Could not find libshout or its development headers. Please install it or compile Mixxx without Shoutcast support using the shoutcast=0 flag.') |
361 | |
362 | - # libvorbisenc only exists on Linux, OSX and mingw32 on Windows. On |
363 | - # Windows with MSVS it is included in vorbisfile.dll. libvorbis and |
364 | - # libogg are included from build.py so don't add here. |
365 | - if not build.platform_is_windows or build.toolchain_is_gnu: |
366 | - vorbisenc_found = conf.CheckLib(['libvorbisenc', 'vorbisenc']) |
367 | - if not vorbisenc_found: |
368 | - raise Exception("libvorbisenc was not found! Please install it or compile Mixxx without Shoutcast support using the shoutcast=0 flag.") |
369 | - |
370 | if build.platform_is_windows and build.static_dependencies: |
371 | conf.CheckLib('winmm') |
372 | conf.CheckLib('ws2_32') |
373 | @@ -817,9 +807,8 @@ |
374 | def sources(self, build): |
375 | build.env.Uic4('dlgprefshoutcastdlg.ui') |
376 | return ['dlgprefshoutcast.cpp', |
377 | - 'engine/engineshoutcast.cpp', |
378 | - 'recording/encodervorbis.cpp', |
379 | - 'recording/encodermp3.cpp'] |
380 | + 'shoutcast/shoutcastmanager.cpp', |
381 | + 'engine/sidechain/engineshoutcast.cpp'] |
382 | |
383 | |
384 | class FFMPEG(Feature): |
385 | |
386 | === modified file 'mixxx/build/qtcreator/mixxx.pro' |
387 | --- mixxx/build/qtcreator/mixxx.pro 2011-11-11 22:18:56 +0000 |
388 | +++ mixxx/build/qtcreator/mixxx.pro 2013-05-16 01:44:29 +0000 |
389 | @@ -98,9 +98,7 @@ |
390 | } |
391 | |
392 | HEADERS += $$UI_DIR/ui_dlgaboutdlg.h \ |
393 | - $$UI_DIR/ui_dlgbpmschemedlg.h \ |
394 | $$UI_DIR/ui_dlgmidilearning.h \ |
395 | - $$UI_DIR/ui_dlgprefbpmdlg.h \ |
396 | $$UI_DIR/ui_dlgprefcontrolsdlg.h \ |
397 | $$UI_DIR/ui_dlgprefcrossfaderdlg.h \ |
398 | $$UI_DIR/ui_dlgprefeqdlg.h \ |
399 | @@ -131,7 +129,6 @@ |
400 | # done |
401 | |
402 | HEADERS += \ |
403 | -$$BASE_DIR/src/analyserbpm.h \ |
404 | $$BASE_DIR/src/analyser.h \ |
405 | $$BASE_DIR/src/analyserqueue.h \ |
406 | $$BASE_DIR/src/analyserwaveform.h \ |
407 | @@ -162,10 +159,8 @@ |
408 | $$BASE_DIR/src/defs_version.h \ |
409 | $$BASE_DIR/src/dlgabout.h \ |
410 | $$BASE_DIR/src/dlgautodj.h \ |
411 | -$$BASE_DIR/src/dlgbpmscheme.h \ |
412 | $$BASE_DIR/src/dlgladspa.h \ |
413 | $$BASE_DIR/src/dlgmidilearning.h \ |
414 | -$$BASE_DIR/src/dlgprefbpm.h \ |
415 | $$BASE_DIR/src/dlgprefcontrols.h \ |
416 | $$BASE_DIR/src/dlgprefcrossfader.h \ |
417 | $$BASE_DIR/src/dlgprefeq.h \ |
418 | @@ -373,7 +368,6 @@ |
419 | |
420 | |
421 | SOURCES += \ |
422 | -$$BASE_DIR/src/analyserbpm.cpp \ |
423 | $$BASE_DIR/src/analyserqueue.cpp \ |
424 | $$BASE_DIR/src/analyserwaveform.cpp \ |
425 | $$BASE_DIR/src/analyserwavesummary.cpp \ |
426 | @@ -396,10 +390,8 @@ |
427 | $$BASE_DIR/src/controlvaluedelegate.cpp \ |
428 | $$BASE_DIR/src/dlgabout.cpp \ |
429 | $$BASE_DIR/src/dlgautodj.cpp \ |
430 | -$$BASE_DIR/src/dlgbpmscheme.cpp \ |
431 | $$BASE_DIR/src/dlgladspa.cpp \ |
432 | $$BASE_DIR/src/dlgmidilearning.cpp \ |
433 | -$$BASE_DIR/src/dlgprefbpm.cpp \ |
434 | $$BASE_DIR/src/dlgprefcontrols.cpp \ |
435 | $$BASE_DIR/src/dlgprefcrossfader.cpp \ |
436 | $$BASE_DIR/src/dlgprefeq.cpp \ |
437 | @@ -622,9 +614,7 @@ |
438 | FORMS += \ |
439 | $$BASE_DIR/src/dlgaboutdlg.ui \ |
440 | $$BASE_DIR/src/dlgautodj.ui \ |
441 | -$$BASE_DIR/src/dlgbpmschemedlg.ui \ |
442 | $$BASE_DIR/src/dlgmidilearning.ui \ |
443 | -$$BASE_DIR/src/dlgprefbpmdlg.ui \ |
444 | $$BASE_DIR/src/dlgprefcontrolsdlg.ui \ |
445 | $$BASE_DIR/src/dlgprefcrossfaderdlg.ui \ |
446 | $$BASE_DIR/src/dlgprefeqdlg.ui \ |
447 | |
448 | === modified file 'mixxx/plugins/soundsourcem4a/SConscript' |
449 | --- mixxx/plugins/soundsourcem4a/SConscript 2011-03-07 22:25:20 +0000 |
450 | +++ mixxx/plugins/soundsourcem4a/SConscript 2013-05-16 01:44:29 +0000 |
451 | @@ -15,7 +15,6 @@ |
452 | "soundsourcem4a.cpp", # MP4/M4A Support through FAAD/libmp4v2 |
453 | ] |
454 | |
455 | - |
456 | #Tell SCons to build the SoundSourceM4A plugin |
457 | #========================= |
458 | if int(build.flags['faad']): |
459 | @@ -24,7 +23,7 @@ |
460 | conf = Configure(env) |
461 | |
462 | have_mp4v2_h = conf.CheckHeader('mp4v2/mp4v2.h') |
463 | - have_mp4 = (have_mp4v2_h and conf.CheckLib(['mp4v2', 'libmp4v2'])) or \ |
464 | + have_mp4 = conf.CheckLib(['mp4v2', 'libmp4v2']) or \ |
465 | conf.CheckLib('mp4') |
466 | |
467 | have_faad = conf.CheckLib(['faad', 'libfaad']) |
468 | |
469 | === modified file 'mixxx/res/controllers/Vestax VCI-300.midi.xml' (properties changed: +x to -x) |
470 | === modified file 'mixxx/res/controllers/Vestax-VCI-300-scripts.js' (properties changed: +x to -x) |
471 | === modified file 'mixxx/res/skins/Outline1024x600-Netbook/CHANGELOG.txt' (properties changed: +x to -x) |
472 | === modified file 'mixxx/res/skins/Outline1024x600-Netbook/skin.xml' (properties changed: +x to -x) |
473 | === modified file 'mixxx/res/skins/Outline1024x768-XGA/CHANGELOG.txt' (properties changed: +x to -x) |
474 | === modified file 'mixxx/res/skins/Outline1024x768-XGA/skin.xml' (properties changed: +x to -x) |
475 | === modified file 'mixxx/res/skins/Outline800x480-WVGA/skin.xml' (properties changed: +x to -x) |
476 | === modified file 'mixxx/res/skins/Shade1024x600-Netbook/skin.xml' |
477 | --- mixxx/res/skins/Shade1024x600-Netbook/skin.xml 2013-05-11 22:59:25 +0000 |
478 | +++ mixxx/res/skins/Shade1024x600-Netbook/skin.xml 2013-05-16 01:44:29 +0000 |
479 | @@ -4133,13 +4133,11 @@ |
480 | <ConfigKey>[Channel1],beatloop_0.125_toggle</ConfigKey> |
481 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
482 | <ButtonState>LeftButton</ButtonState> |
483 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
484 | </Connection> |
485 | <Connection> |
486 | <ConfigKey>[Channel1],beatlooproll_0.125_activate</ConfigKey> |
487 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
488 | <ButtonState>RightButton</ButtonState> |
489 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
490 | </Connection> |
491 | <Connection> |
492 | <ConfigKey>[Channel1],beatloop_0.125_enabled</ConfigKey> |
493 | @@ -4167,13 +4165,11 @@ |
494 | <ConfigKey>[Channel1],beatloop_0.25_toggle</ConfigKey> |
495 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
496 | <ButtonState>LeftButton</ButtonState> |
497 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
498 | </Connection> |
499 | <Connection> |
500 | <ConfigKey>[Channel1],beatlooproll_0.25_activate</ConfigKey> |
501 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
502 | <ButtonState>RightButton</ButtonState> |
503 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
504 | </Connection> |
505 | <Connection> |
506 | <ConfigKey>[Channel1],beatloop_0.25_enabled</ConfigKey> |
507 | @@ -4201,13 +4197,11 @@ |
508 | <ConfigKey>[Channel1],beatloop_0.5_toggle</ConfigKey> |
509 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
510 | <ButtonState>LeftButton</ButtonState> |
511 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
512 | </Connection> |
513 | <Connection> |
514 | <ConfigKey>[Channel1],beatlooproll_0.5_activate</ConfigKey> |
515 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
516 | <ButtonState>RightButton</ButtonState> |
517 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
518 | </Connection> |
519 | <Connection> |
520 | <ConfigKey>[Channel1],beatloop_0.5_enabled</ConfigKey> |
521 | @@ -4235,13 +4229,11 @@ |
522 | <ConfigKey>[Channel1],beatloop_1_toggle</ConfigKey> |
523 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
524 | <ButtonState>LeftButton</ButtonState> |
525 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
526 | </Connection> |
527 | <Connection> |
528 | <ConfigKey>[Channel1],beatlooproll_1_activate</ConfigKey> |
529 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
530 | <ButtonState>RightButton</ButtonState> |
531 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
532 | </Connection> |
533 | <Connection> |
534 | <ConfigKey>[Channel1],beatloop_1_enabled</ConfigKey> |
535 | @@ -4269,13 +4261,11 @@ |
536 | <ConfigKey>[Channel1],beatloop_2_toggle</ConfigKey> |
537 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
538 | <ButtonState>LeftButton</ButtonState> |
539 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
540 | </Connection> |
541 | <Connection> |
542 | <ConfigKey>[Channel1],beatlooproll_2_activate</ConfigKey> |
543 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
544 | <ButtonState>RightButton</ButtonState> |
545 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
546 | </Connection> |
547 | <Connection> |
548 | <ConfigKey>[Channel1],beatloop_2_enabled</ConfigKey> |
549 | @@ -4303,13 +4293,11 @@ |
550 | <ConfigKey>[Channel1],beatloop_4_toggle</ConfigKey> |
551 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
552 | <ButtonState>LeftButton</ButtonState> |
553 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
554 | </Connection> |
555 | <Connection> |
556 | <ConfigKey>[Channel1],beatlooproll_4_activate</ConfigKey> |
557 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
558 | <ButtonState>RightButton</ButtonState> |
559 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
560 | </Connection> |
561 | <Connection> |
562 | <ConfigKey>[Channel1],beatloop_4_enabled</ConfigKey> |
563 | @@ -4337,13 +4325,11 @@ |
564 | <ConfigKey>[Channel1],beatloop_8_toggle</ConfigKey> |
565 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
566 | <ButtonState>LeftButton</ButtonState> |
567 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
568 | </Connection> |
569 | <Connection> |
570 | <ConfigKey>[Channel1],beatlooproll_8_activate</ConfigKey> |
571 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
572 | <ButtonState>RightButton</ButtonState> |
573 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
574 | </Connection> |
575 | <Connection> |
576 | <ConfigKey>[Channel1],beatloop_8_enabled</ConfigKey> |
577 | @@ -4371,13 +4357,11 @@ |
578 | <ConfigKey>[Channel1],beatloop_16_toggle</ConfigKey> |
579 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
580 | <ButtonState>LeftButton</ButtonState> |
581 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
582 | </Connection> |
583 | <Connection> |
584 | <ConfigKey>[Channel1],beatlooproll_16_activate</ConfigKey> |
585 | <EmitOnPressAndRelease>true</EmitOnPressAndRelease> |
586 | <ButtonState>RightButton</ButtonState> |
587 | - <ConnectValueToWidget>false</ConnectValueToWidget> |
588 | </Connection> |
589 | <Connection> |
590 | <ConfigKey>[Channel1],beatloop_16_enabled</ConfigKey> |
591 | |
592 | === removed file 'mixxx/src/analyserbpm.cpp' |
593 | --- mixxx/src/analyserbpm.cpp 2013-01-30 05:31:23 +0000 |
594 | +++ mixxx/src/analyserbpm.cpp 1970-01-01 00:00:00 +0000 |
595 | @@ -1,102 +0,0 @@ |
596 | -#include <QtDebug> |
597 | - |
598 | -#undef TRUE |
599 | -#undef FALSE |
600 | -#include "BPMDetect.h" |
601 | - |
602 | -#include "trackinfoobject.h" |
603 | -#include "track/beatgrid.h" |
604 | -#include "track/beatfactory.h" |
605 | -#include "track/beatutils.h" |
606 | -#include "analyserbpm.h" |
607 | - |
608 | -AnalyserBPM::AnalyserBPM(ConfigObject<ConfigValue> *_config) : |
609 | - m_pConfig(_config), |
610 | - m_pDetector(NULL), |
611 | - m_iMinBpm(0), |
612 | - m_iMaxBpm(0), |
613 | - m_bProcessEntireSong(true) { |
614 | -} |
615 | - |
616 | -bool AnalyserBPM::initialise(TrackPointer tio, int sampleRate, int totalSamples) { |
617 | - Q_UNUSED(totalSamples); |
618 | - if (loadStored(tio)) { |
619 | - return false; |
620 | - } |
621 | - |
622 | - m_iMinBpm = m_pConfig->getValueString(ConfigKey("[BPM]","BPMRangeStart")).toInt(); |
623 | - m_iMaxBpm = m_pConfig->getValueString(ConfigKey("[BPM]","BPMRangeEnd")).toInt(); |
624 | - m_bProcessEntireSong = (bool)m_pConfig->getValueString(ConfigKey("[BPM]","AnalyzeEntireSong")).toInt(); |
625 | - |
626 | - // All SoundSource's return stereo data, no matter the real file's type |
627 | - m_pDetector = new soundtouch::BPMDetect(2, sampleRate); |
628 | - //m_pDetector = new BPMDetect(tio->getChannels(), sampleRate); |
629 | - // defaultrange ? MIN_BPM : m_iMinBpm, |
630 | - // defaultrange ? MAX_BPM : m_iMaxBpm); |
631 | - return true; |
632 | -} |
633 | - |
634 | -bool AnalyserBPM::loadStored(TrackPointer tio) const { |
635 | - bool bpmEnabled = (bool)m_pConfig->getValueString(ConfigKey("[BPM]","BPMDetectionEnabled")).toInt(); |
636 | - // If BPM detection is enabled and the track does not have a BPM already, |
637 | - // create a detector. |
638 | - if(bpmEnabled && tio->getBpm() <= 0.0) { |
639 | - return false; |
640 | - } |
641 | - return true; |
642 | -} |
643 | - |
644 | -void AnalyserBPM::process(const CSAMPLE *pIn, const int iLen) { |
645 | - // Check if BPM detection is enabled |
646 | - if(m_pDetector == NULL) { |
647 | - return; |
648 | - } |
649 | - //qDebug() << "AnalyserBPM::process() processing " << iLen << " samples"; |
650 | - |
651 | - m_pDetector->inputSamples(pIn, iLen/2); |
652 | -} |
653 | - |
654 | -void AnalyserBPM::cleanup(TrackPointer tio) |
655 | -{ |
656 | - Q_UNUSED(tio); |
657 | - if(m_pDetector != NULL) |
658 | - { |
659 | - delete m_pDetector; |
660 | - m_pDetector = NULL; |
661 | - } |
662 | -} |
663 | - |
664 | -void AnalyserBPM::finalise(TrackPointer tio) { |
665 | - // Check if BPM detection is enabled |
666 | - if(m_pDetector == NULL) { |
667 | - return; |
668 | - } |
669 | - |
670 | - double bpm = m_pDetector->getBpm(); |
671 | - if (bpm != 0) { |
672 | - // Shift it by 2's until it is in the desired range |
673 | - double newbpm = BeatUtils::constrainBpm( |
674 | - bpm, m_iMinBpm, m_iMaxBpm, |
675 | - static_cast<bool>(m_pConfig->getValueString( |
676 | - ConfigKey("[BPM]", "BPMAboveRangeEnabled")).toInt())); |
677 | - |
678 | - // Currently, the BPM is only analyzed if the track has no BPM. This |
679 | - // means we don't have to worry that the track already has an existing |
680 | - // BeatGrid. |
681 | - BeatsPointer pBeats = BeatFactory::makeBeatGrid(tio.data(), newbpm, 0.0f); |
682 | - tio->setBeats(pBeats); |
683 | - |
684 | - //if(pBpmReceiver) { |
685 | - //pBpmReceiver->setComplete(tio, false, bpm); |
686 | - //} |
687 | - //qDebug() << "AnalyserBPM BPM detection successful for" << tio->getFilename(); |
688 | - //qDebug() << "AnalyserBPM BPM is " << newbpm << " (raw: " << bpm << ")"; |
689 | - } else { |
690 | - //qDebug() << "AnalyserBPM BPM detection failed, setting to 0."; |
691 | - } |
692 | - |
693 | - // Cleanup the BPM detector |
694 | - delete m_pDetector; |
695 | - m_pDetector = NULL; |
696 | - |
697 | -} |
698 | |
699 | === removed file 'mixxx/src/analyserbpm.h' |
700 | --- mixxx/src/analyserbpm.h 2012-12-13 23:22:57 +0000 |
701 | +++ mixxx/src/analyserbpm.h 1970-01-01 00:00:00 +0000 |
702 | @@ -1,27 +0,0 @@ |
703 | -#ifndef ANALYSER_BPM_H |
704 | -#define ANALYSER_BPM_H |
705 | - |
706 | -#include "analyser.h" |
707 | -#include "configobject.h" |
708 | - |
709 | -namespace soundtouch { |
710 | -class BPMDetect; |
711 | -} |
712 | - |
713 | -class AnalyserBPM : public Analyser { |
714 | - public: |
715 | - AnalyserBPM(ConfigObject<ConfigValue> *_config); |
716 | - bool initialise(TrackPointer tio, int sampleRate, int totalSamples); |
717 | - bool loadStored(TrackPointer tio) const; |
718 | - void process(const CSAMPLE *pIn, const int iLen); |
719 | - void cleanup(TrackPointer tio); |
720 | - void finalise(TrackPointer tio); |
721 | - |
722 | - private: |
723 | - ConfigObject<ConfigValue> *m_pConfig; |
724 | - soundtouch::BPMDetect *m_pDetector; |
725 | - int m_iMinBpm, m_iMaxBpm; |
726 | - bool m_bProcessEntireSong; |
727 | -}; |
728 | - |
729 | -#endif |
730 | |
731 | === modified file 'mixxx/src/analyserqueue.cpp' |
732 | --- mixxx/src/analyserqueue.cpp 2013-02-28 20:30:15 +0000 |
733 | +++ mixxx/src/analyserqueue.cpp 2013-05-16 01:44:29 +0000 |
734 | @@ -14,12 +14,9 @@ |
735 | #endif |
736 | |
737 | #include "analyserwaveform.h" |
738 | -#include "analyserbpm.h" |
739 | #include "analyserrg.h" |
740 | -#ifdef __VAMP__ |
741 | #include "analyserbeats.h" |
742 | #include "vamp/vampanalyser.h" |
743 | -#endif |
744 | |
745 | #include <typeinfo> |
746 | |
747 | @@ -407,13 +404,9 @@ |
748 | |
749 | ret->addAnalyser(new AnalyserWaveform(_config)); |
750 | ret->addAnalyser(new AnalyserGain(_config)); |
751 | -#ifdef __VAMP__ |
752 | VampAnalyser::initializePluginPaths(); |
753 | ret->addAnalyser(new AnalyserBeats(_config)); |
754 | //ret->addAnalyser(new AnalyserVampKeyTest(_config)); |
755 | -#else |
756 | - ret->addAnalyser(new AnalyserBPM(_config)); |
757 | -#endif |
758 | |
759 | ret->start(QThread::IdlePriority); |
760 | return ret; |
761 | @@ -426,13 +419,9 @@ |
762 | |
763 | ret->addAnalyser(new AnalyserWaveform(_config)); |
764 | ret->addAnalyser(new AnalyserGain(_config)); |
765 | -#ifdef __VAMP__ |
766 | VampAnalyser::initializePluginPaths(); |
767 | ret->addAnalyser(new AnalyserBeats(_config)); |
768 | //ret->addAnalyser(new AnalyserVampKeyTest(_config)); |
769 | -#else |
770 | - ret->addAnalyser(new AnalyserBPM(_config)); |
771 | -#endif |
772 | |
773 | ret->start(QThread::IdlePriority); |
774 | return ret; |
775 | |
776 | === added directory 'mixxx/src/control' |
777 | === added file 'mixxx/src/control/control.cpp' |
778 | --- mixxx/src/control/control.cpp 1970-01-01 00:00:00 +0000 |
779 | +++ mixxx/src/control/control.cpp 2013-05-16 01:44:29 +0000 |
780 | @@ -0,0 +1,132 @@ |
781 | +#include <QtDebug> |
782 | +#include <QMutexLocker> |
783 | + |
784 | +#include "control/control.h" |
785 | + |
786 | +#include "util/stat.h" |
787 | +#include "util/timer.h" |
788 | + |
789 | +// Static member variable definition |
790 | +QHash<ConfigKey, ControlDoublePrivate*> ControlDoublePrivate::m_sqCOHash; |
791 | +QMutex ControlDoublePrivate::m_sqCOHashMutex; |
792 | + |
793 | +ControlDoublePrivate::ControlDoublePrivate() |
794 | + : m_bIgnoreNops(true), |
795 | + m_bTrack(false) { |
796 | + m_defaultValue.setValue(0); |
797 | + m_value.setValue(0); |
798 | +} |
799 | + |
800 | +ControlDoublePrivate::ControlDoublePrivate(ConfigKey key, |
801 | + bool bIgnoreNops, bool bTrack) |
802 | + : m_key(key), |
803 | + m_bIgnoreNops(bIgnoreNops), |
804 | + m_bTrack(bTrack), |
805 | + m_trackKey("control " + m_key.group + "," + m_key.item), |
806 | + m_trackType(Stat::UNSPECIFIED), |
807 | + m_trackFlags(Stat::COUNT | Stat::SUM | Stat::AVERAGE | |
808 | + Stat::SAMPLE_VARIANCE | Stat::MIN | Stat::MAX) { |
809 | + m_defaultValue.setValue(0); |
810 | + m_value.setValue(0); |
811 | + |
812 | + m_sqCOHashMutex.lock(); |
813 | + m_sqCOHash.insert(m_key, this); |
814 | + m_sqCOHashMutex.unlock(); |
815 | + |
816 | + if (m_bTrack) { |
817 | + // TODO(rryan): Make configurable. |
818 | + Stat::track(m_trackKey, static_cast<Stat::StatType>(m_trackType), |
819 | + static_cast<Stat::ComputeFlags>(m_trackFlags), |
820 | + m_value.getValue()); |
821 | + } |
822 | +} |
823 | + |
824 | +ControlDoublePrivate::~ControlDoublePrivate() { |
825 | + m_sqCOHashMutex.lock(); |
826 | + m_sqCOHash.remove(m_key); |
827 | + m_sqCOHashMutex.unlock(); |
828 | +} |
829 | + |
830 | +// static |
831 | +ControlDoublePrivate* ControlDoublePrivate::getControl( |
832 | + const ConfigKey& key, bool bCreate, bool bIgnoreNops, bool bTrack) { |
833 | + QMutexLocker locker(&m_sqCOHashMutex); |
834 | + QHash<ConfigKey, ControlDoublePrivate*>::const_iterator it = m_sqCOHash.find(key); |
835 | + if (it != m_sqCOHash.end()) { |
836 | + return it.value(); |
837 | + } |
838 | + locker.unlock(); |
839 | + |
840 | + ControlDoublePrivate* pControl = NULL; |
841 | + if (bCreate) { |
842 | + pControl = new ControlDoublePrivate(key, bIgnoreNops, bTrack); |
843 | + locker.relock(); |
844 | + m_sqCOHash.insert(key, pControl); |
845 | + locker.unlock(); |
846 | + } |
847 | + |
848 | + if (pControl == NULL) { |
849 | + qWarning() << "ControlDoublePrivate::getControl returning NULL for (" |
850 | + << key.group << "," << key.item << ")"; |
851 | + } |
852 | + |
853 | + return pControl; |
854 | +} |
855 | + |
856 | +double ControlDoublePrivate::get() const { |
857 | + return m_value.getValue(); |
858 | +} |
859 | + |
860 | +void ControlDoublePrivate::reset(QObject* pSender) { |
861 | + double defaultValue = m_defaultValue.getValue(); |
862 | + set(defaultValue, pSender); |
863 | +} |
864 | + |
865 | +void ControlDoublePrivate::set(const double& value, QObject* pSender) { |
866 | + if (m_bIgnoreNops && get() == value) { |
867 | + return; |
868 | + } |
869 | + |
870 | + double dValue = value; |
871 | + // The behavior says to ignore the set, ignore it. |
872 | + ControlNumericBehavior* pBehavior = m_pBehavior; |
873 | + if (pBehavior && !pBehavior->setFilter(&dValue)) { |
874 | + return; |
875 | + } |
876 | + m_value.setValue(dValue); |
877 | + emit(valueChanged(dValue, pSender)); |
878 | + |
879 | + if (m_bTrack) { |
880 | + Stat::track(m_trackKey, static_cast<Stat::StatType>(m_trackType), |
881 | + static_cast<Stat::ComputeFlags>(m_trackFlags), dValue); |
882 | + } |
883 | +} |
884 | + |
885 | +ControlNumericBehavior* ControlDoublePrivate::setBehavior(ControlNumericBehavior* pBehavior) { |
886 | + return m_pBehavior.fetchAndStoreRelaxed(pBehavior); |
887 | +} |
888 | + |
889 | +void ControlDoublePrivate::setWidgetParameter(double dParam, QObject* pSetter) { |
890 | + ControlNumericBehavior* pBehavior = m_pBehavior; |
891 | + set(pBehavior ? pBehavior->widgetParameterToValue(dParam) : dParam, pSetter); |
892 | +} |
893 | + |
894 | +double ControlDoublePrivate::getWidgetParameter() const { |
895 | + ControlNumericBehavior* pBehavior = m_pBehavior; |
896 | + return pBehavior ? pBehavior->valueToWidgetParameter(get()) : get(); |
897 | +} |
898 | + |
899 | +void ControlDoublePrivate::setMidiParameter(MidiOpCode opcode, double dParam) { |
900 | + ControlNumericBehavior* pBehavior = m_pBehavior; |
901 | + if (pBehavior) { |
902 | + pBehavior->setValueFromMidiParameter(opcode, dParam, this); |
903 | + } else { |
904 | + set(dParam, NULL); |
905 | + } |
906 | +} |
907 | + |
908 | +double ControlDoublePrivate::getMidiParameter() const { |
909 | + ControlNumericBehavior* pBehavior = m_pBehavior; |
910 | + return pBehavior ? pBehavior->valueToMidiParameter(get()) : get(); |
911 | +} |
912 | + |
913 | |
914 | === added file 'mixxx/src/control/control.h' |
915 | --- mixxx/src/control/control.h 1970-01-01 00:00:00 +0000 |
916 | +++ mixxx/src/control/control.h 2013-05-16 01:44:29 +0000 |
917 | @@ -0,0 +1,95 @@ |
918 | +#ifndef CONTROL_H |
919 | +#define CONTROL_H |
920 | + |
921 | +#include <QHash> |
922 | +#include <QMutex> |
923 | +#include <QString> |
924 | +#include <QObject> |
925 | +#include <QAtomicPointer> |
926 | + |
927 | +#include "control/controlbehavior.h" |
928 | +#include "control/controlvalue.h" |
929 | +#include "configobject.h" |
930 | + |
931 | +class ControlDoublePrivate : public QObject { |
932 | + Q_OBJECT |
933 | + public: |
934 | + ControlDoublePrivate(); |
935 | + ControlDoublePrivate(ConfigKey key, bool bIgnoreNops, bool bTrack); |
936 | + virtual ~ControlDoublePrivate(); |
937 | + |
938 | + // Gets the ControlDoublePrivate matching the given ConfigKey. If bCreate |
939 | + // is true, allocates a new ControlDoublePrivate for the ConfigKey if one |
940 | + // does not exist. |
941 | + static ControlDoublePrivate* getControl( |
942 | + const ConfigKey& key, |
943 | + bool bCreate, bool bIgnoreNops=true, bool bTrack=false); |
944 | + static inline ControlDoublePrivate* getControl( |
945 | + const QString& group, const QString& item, |
946 | + bool bCreate, bool bIgnoreNops=true, bool bTrack=false) { |
947 | + ConfigKey key(group, item); |
948 | + return getControl(key, bCreate, bIgnoreNops, bTrack); |
949 | + } |
950 | + |
951 | + // Sets the control value. |
952 | + void set(const double& value, QObject* pSetter); |
953 | + // Gets the control value. |
954 | + double get() const; |
955 | + // Resets the control value to its default. |
956 | + void reset(QObject* pSetter); |
957 | + |
958 | + // Set the behavior to be used when setting values and translating between |
959 | + // parameter and value space. Returns the previously set behavior (if any). |
960 | + // Caller must handle appropriate destruction of the previous behavior or |
961 | + // memory will leak. |
962 | + ControlNumericBehavior* setBehavior(ControlNumericBehavior* pBehavior); |
963 | + |
964 | + void setWidgetParameter(double dParam, QObject* pSetter); |
965 | + double getWidgetParameter() const; |
966 | + |
967 | + void setMidiParameter(MidiOpCode opcode, double dParam); |
968 | + double getMidiParameter() const; |
969 | + |
970 | + inline bool ignoreNops() const { |
971 | + return m_bIgnoreNops; |
972 | + } |
973 | + |
974 | + inline void setDefaultValue(double dValue) { |
975 | + m_defaultValue.setValue(dValue); |
976 | + } |
977 | + inline double defaultValue() const { |
978 | + double default_value = m_defaultValue.getValue(); |
979 | + return m_pBehavior ? m_pBehavior->defaultValue(default_value) : default_value; |
980 | + } |
981 | + |
982 | + signals: |
983 | + // Emitted when the ControlDoublePrivate value changes. pSetter is a |
984 | + // pointer to the setter of the value (potentially NULL). |
985 | + void valueChanged(double value, QObject* pSetter); |
986 | + |
987 | + private: |
988 | + ConfigKey m_key; |
989 | + // Whether to ignore sets which would have no effect. |
990 | + bool m_bIgnoreNops; |
991 | + |
992 | + // Whether to track value changes with the stats framework. |
993 | + bool m_bTrack; |
994 | + QString m_trackKey; |
995 | + int m_trackType; |
996 | + int m_trackFlags; |
997 | + |
998 | + // The control value. |
999 | + ControlValueAtomic<double> m_value; |
1000 | + // The default control value. |
1001 | + ControlValueAtomic<double> m_defaultValue; |
1002 | + |
1003 | + QAtomicPointer<ControlNumericBehavior> m_pBehavior; |
1004 | + |
1005 | + // Hash of ControlDoublePrivate instantiations. |
1006 | + static QHash<ConfigKey,ControlDoublePrivate*> m_sqCOHash; |
1007 | + // Mutex guarding access to the ControlDoublePrivate hash. |
1008 | + static QMutex m_sqCOHashMutex; |
1009 | +}; |
1010 | + |
1011 | + |
1012 | +#endif /* CONTROL_H */ |
1013 | |
1014 | === added file 'mixxx/src/control/controlbehavior.cpp' |
1015 | --- mixxx/src/control/controlbehavior.cpp 1970-01-01 00:00:00 +0000 |
1016 | +++ mixxx/src/control/controlbehavior.cpp 2013-05-16 01:44:29 +0000 |
1017 | @@ -0,0 +1,63 @@ |
1018 | +#include "control/controlbehavior.h" |
1019 | +#include "control/control.h" |
1020 | + |
1021 | +// static |
1022 | +const int ControlPushButtonBehavior::kPowerWindowTimeMillis = 300; |
1023 | + |
1024 | +void ControlNumericBehavior::setValueFromMidiParameter(MidiOpCode o, double dParam, |
1025 | + ControlDoublePrivate* pControl) { |
1026 | + Q_UNUSED(o); |
1027 | + pControl->set(dParam, NULL); |
1028 | +} |
1029 | + |
1030 | +void ControlPotmeterBehavior::setValueFromMidiParameter(MidiOpCode o, double dParam, |
1031 | + ControlDoublePrivate* pControl) { |
1032 | + Q_UNUSED(o); |
1033 | + pControl->set(widgetParameterToValue(dParam), NULL); |
1034 | +} |
1035 | + |
1036 | +void ControlPushButtonBehavior::setValueFromMidiParameter( |
1037 | + MidiOpCode o, double dParam, ControlDoublePrivate* pControl) { |
1038 | + // This block makes push-buttons act as power window buttons. |
1039 | + if (m_buttonMode == POWERWINDOW && m_iNumStates == 2) { |
1040 | + if (o == MIDI_NOTE_ON) { |
1041 | + if (dParam > 0.) { |
1042 | + double value = pControl->get(); |
1043 | + pControl->set(!value, NULL); |
1044 | + m_pushTimer.setSingleShot(true); |
1045 | + m_pushTimer.start(kPowerWindowTimeMillis); |
1046 | + } |
1047 | + } else if (o == MIDI_NOTE_OFF) { |
1048 | + if (!m_pushTimer.isActive()) { |
1049 | + pControl->set(0.0, NULL); |
1050 | + } |
1051 | + } |
1052 | + } else if (m_buttonMode == TOGGLE) { |
1053 | + // This block makes push-buttons act as toggle buttons. |
1054 | + if (m_iNumStates > 2) { //multistate button |
1055 | + if (dParam > 0.) { //looking for NOTE_ON doesn't seem to work... |
1056 | + double value = pControl->get(); |
1057 | + value++; |
1058 | + if (value >= m_iNumStates) { |
1059 | + pControl->set(0, NULL); |
1060 | + } else { |
1061 | + pControl->set(value, NULL); |
1062 | + } |
1063 | + } |
1064 | + } else { |
1065 | + if (o == MIDI_NOTE_ON) { |
1066 | + if (dParam > 0.) { |
1067 | + double value = pControl->get(); |
1068 | + pControl->set(!value, NULL); |
1069 | + } |
1070 | + } |
1071 | + } |
1072 | + } else { //Not a toggle button (trigger only when button pushed) |
1073 | + if (o == MIDI_NOTE_ON) { |
1074 | + double value = pControl->get(); |
1075 | + pControl->set(!value, NULL); |
1076 | + } else if (o == MIDI_NOTE_OFF) { |
1077 | + pControl->set(0.0, NULL); |
1078 | + } |
1079 | + } |
1080 | +} |
1081 | |
1082 | === added file 'mixxx/src/control/controlbehavior.h' |
1083 | --- mixxx/src/control/controlbehavior.h 1970-01-01 00:00:00 +0000 |
1084 | +++ mixxx/src/control/controlbehavior.h 2013-05-16 01:44:29 +0000 |
1085 | @@ -0,0 +1,186 @@ |
1086 | +#ifndef CONTROLBEHAVIOR_H |
1087 | +#define CONTROLBEHAVIOR_H |
1088 | + |
1089 | +#include <math.h> |
1090 | + |
1091 | +#include <QTimer> |
1092 | + |
1093 | +#include "controllers/midi/midimessage.h" |
1094 | +#include "mathstuff.h" |
1095 | + |
1096 | +class ControlDoublePrivate; |
1097 | + |
1098 | +class ControlNumericBehavior { |
1099 | + public: |
1100 | + // Returns true if the set should occur. Mutates dValue if the value should |
1101 | + // be changed. |
1102 | + virtual bool setFilter(double* dValue) { |
1103 | + Q_UNUSED(dValue); |
1104 | + return true; |
1105 | + } |
1106 | + |
1107 | + virtual double defaultValue(double dDefault) const { |
1108 | + return dDefault; |
1109 | + } |
1110 | + |
1111 | + virtual double valueToWidgetParameter(double dValue) { |
1112 | + return dValue; |
1113 | + } |
1114 | + |
1115 | + virtual double widgetParameterToValue(double dParam) { |
1116 | + return dParam; |
1117 | + } |
1118 | + |
1119 | + virtual double valueToMidiParameter(double dValue) { |
1120 | + return dValue; |
1121 | + } |
1122 | + |
1123 | + virtual void setValueFromMidiParameter(MidiOpCode o, double dParam, |
1124 | + ControlDoublePrivate* pControl); |
1125 | +}; |
1126 | + |
1127 | +class ControlPotmeterBehavior : public ControlNumericBehavior { |
1128 | + public: |
1129 | + ControlPotmeterBehavior(double dMinValue, double dMaxValue) |
1130 | + : m_dMinValue(dMinValue), |
1131 | + m_dMaxValue(dMaxValue), |
1132 | + m_dValueRange(m_dMaxValue - m_dMinValue), |
1133 | + m_dDefaultValue(m_dMinValue + 0.5 * m_dValueRange) { |
1134 | + } |
1135 | + |
1136 | + virtual bool setFilter(double* dValue) { |
1137 | + if (*dValue > m_dMaxValue) { |
1138 | + *dValue = m_dMaxValue; |
1139 | + } else if (*dValue < m_dMinValue) { |
1140 | + *dValue = m_dMinValue; |
1141 | + } |
1142 | + return true; |
1143 | + } |
1144 | + |
1145 | + virtual double defaultValue(double dDefault) const { |
1146 | + Q_UNUSED(dDefault); |
1147 | + return m_dDefaultValue; |
1148 | + } |
1149 | + |
1150 | + virtual double valueToWidgetParameter(double dValue) { |
1151 | + double dNorm = (dValue - m_dMinValue) / m_dValueRange; |
1152 | + return dNorm < 0.5 ? dNorm * 128.0 : dNorm * 126.0 + 1.0; |
1153 | + } |
1154 | + |
1155 | + virtual double widgetParameterToValue(double dParam) { |
1156 | + double dNorm = dParam < 64 ? dParam / 128.0 : (dParam - 1.0) / 126.0; |
1157 | + return m_dMinValue + dNorm * m_dValueRange; |
1158 | + } |
1159 | + |
1160 | + virtual double valueToMidiParameter(double dValue) { |
1161 | + return valueToWidgetParameter(dValue); |
1162 | + } |
1163 | + |
1164 | + virtual void setValueFromMidiParameter(MidiOpCode o, double dParam, |
1165 | + ControlDoublePrivate* pControl); |
1166 | + |
1167 | + protected: |
1168 | + double m_dMinValue; |
1169 | + double m_dMaxValue; |
1170 | + double m_dValueRange; |
1171 | + double m_dDefaultValue; |
1172 | +}; |
1173 | + |
1174 | +#define maxPosition 127 |
1175 | +#define minPosition 0 |
1176 | +#define middlePosition ((maxPosition-minPosition)/2) |
1177 | +#define positionrange (maxPosition-minPosition) |
1178 | + |
1179 | +class ControlLogpotmeterBehavior : public ControlPotmeterBehavior { |
1180 | + public: |
1181 | + ControlLogpotmeterBehavior(double dMaxValue) : ControlPotmeterBehavior(0, dMaxValue) { |
1182 | + m_dB1 = log10(2.0) / middlePosition; |
1183 | + m_dB2 = log10(dMaxValue) / (maxPosition - middlePosition); |
1184 | + } |
1185 | + |
1186 | + virtual double defaultValue(double dDefault) { |
1187 | + Q_UNUSED(dDefault); |
1188 | + return 1.0; |
1189 | + } |
1190 | + |
1191 | + virtual double valueToWidgetParameter(double dValue) { |
1192 | + if (dValue > 1.0) { |
1193 | + return log10(dValue) / m_dB2 + middlePosition; |
1194 | + } else { |
1195 | + return log10(dValue + 1.0) / m_dB1; |
1196 | + } |
1197 | + } |
1198 | + |
1199 | + virtual double widgetParameterToValue(double dParam) { |
1200 | + if (dParam <= middlePosition) { |
1201 | + return pow(10.0, m_dB1 * dParam) - 1; |
1202 | + } else { |
1203 | + return pow(10.0, m_dB2 * (dParam - middlePosition)); |
1204 | + } |
1205 | + } |
1206 | + |
1207 | + protected: |
1208 | + double m_dB1, m_dB2; |
1209 | +}; |
1210 | + |
1211 | +class ControlLinPotmeterBehavior : public ControlPotmeterBehavior { |
1212 | + public: |
1213 | + ControlLinPotmeterBehavior(double dMinValue, double dMaxValue) |
1214 | + : ControlPotmeterBehavior(dMinValue, dMaxValue) { |
1215 | + } |
1216 | + |
1217 | + virtual double valueToWidgetParameter(double dValue) { |
1218 | + double dNorm = (dValue - m_dMinValue) / m_dValueRange; |
1219 | + return math_min(dNorm * 128, 127); |
1220 | + } |
1221 | + |
1222 | + virtual double widgetParameterToValue(double dParam) { |
1223 | + double dNorm = dParam / 128.0; |
1224 | + return m_dMinValue + dNorm * m_dValueRange; |
1225 | + } |
1226 | +}; |
1227 | + |
1228 | +class ControlTTRotaryBehavior : public ControlNumericBehavior { |
1229 | + public: |
1230 | + virtual double valueToWidgetParameter(double dValue) { |
1231 | + return dValue * 200.0 + 64; |
1232 | + } |
1233 | + |
1234 | + virtual double widgetParameterToValue(double dParam) { |
1235 | + // Non-linear scaling |
1236 | + double temp = ((dParam - 64.0) * (dParam - 64.0)) / 64.0; |
1237 | + if (dParam - 64 < 0) { |
1238 | + temp = -temp; |
1239 | + } |
1240 | + return temp; |
1241 | + } |
1242 | +}; |
1243 | + |
1244 | +class ControlPushButtonBehavior : public ControlNumericBehavior { |
1245 | + public: |
1246 | + static const int kPowerWindowTimeMillis; |
1247 | + |
1248 | + // TODO(XXX) Duplicated from ControlPushButton. It's complicated and |
1249 | + // annoying to share them so I just copied them. |
1250 | + enum ButtonMode { |
1251 | + PUSH = 0, |
1252 | + TOGGLE, |
1253 | + POWERWINDOW |
1254 | + }; |
1255 | + |
1256 | + ControlPushButtonBehavior(ButtonMode buttonMode, |
1257 | + int iNumStates) |
1258 | + : m_buttonMode(buttonMode), |
1259 | + m_iNumStates(iNumStates) { |
1260 | + } |
1261 | + |
1262 | + virtual void setValueFromMidiParameter(MidiOpCode o, double dParam, |
1263 | + ControlDoublePrivate* pControl); |
1264 | + |
1265 | + private: |
1266 | + ButtonMode m_buttonMode; |
1267 | + int m_iNumStates; |
1268 | + QTimer m_pushTimer; |
1269 | +}; |
1270 | + |
1271 | +#endif /* CONTROLBEHAVIOR_H */ |
1272 | |
1273 | === renamed file 'mixxx/src/controlobjectbase.h' => 'mixxx/src/control/controlvalue.h' |
1274 | --- mixxx/src/controlobjectbase.h 2013-05-15 20:33:26 +0000 |
1275 | +++ mixxx/src/control/controlvalue.h 2013-05-16 01:44:29 +0000 |
1276 | @@ -1,28 +1,34 @@ |
1277 | +#ifndef CONTROLVALUE_H |
1278 | +#define CONTROLVALUE_H |
1279 | |
1280 | -#ifndef CONTROLOBJECTBASE_H_ |
1281 | -#define CONTROLOBJECTBASE_H_ |
1282 | +#include <limits> |
1283 | |
1284 | #include <QAtomicInt> |
1285 | #include <QObject> |
1286 | -#include <limits> |
1287 | |
1288 | // for look free access, this value has to be >= the number of value using threads |
1289 | // value must be a fraction of an integer |
1290 | const int cRingSize = 8; |
1291 | -// there are basicly unlimited readers allowed at each ring element |
1292 | +// there are basicly unlimited readers allowed at each ring element |
1293 | // but we have to count them so max() is just fine. |
1294 | const int cReaderSlotCnt = std::numeric_limits<int>::max(); |
1295 | |
1296 | - |
1297 | +// A single instance of a value of type T along with an atomic integer which |
1298 | +// tracks the current number of readers or writers of the slot. The value |
1299 | +// m_readerSlots starts at cReaderSlotCnt and counts down to 0. If the value is |
1300 | +// 0 or less then reads to the value fail because there are either too many |
1301 | +// readers or a write is occurring. A write to the value will fail if |
1302 | +// m_readerSlots is not equal to cReaderSlotCnt (e.g. there is an active |
1303 | +// reader). |
1304 | template<typename T> |
1305 | -class ControlObjectRingValue { |
1306 | +class ControlRingValue { |
1307 | public: |
1308 | - ControlObjectRingValue() |
1309 | + ControlRingValue() |
1310 | : m_value(T()), |
1311 | m_readerSlots(cReaderSlotCnt) { |
1312 | } |
1313 | |
1314 | - bool tryGet(T* value) { |
1315 | + bool tryGet(T* value) const { |
1316 | // Read while consuming one readerSlot |
1317 | bool hasSlot = (m_readerSlots.fetchAndAddAcquire(-1) > 0); |
1318 | if (hasSlot) { |
1319 | @@ -44,14 +50,19 @@ |
1320 | |
1321 | private: |
1322 | T m_value; |
1323 | - QAtomicInt m_readerSlots; |
1324 | + mutable QAtomicInt m_readerSlots; |
1325 | }; |
1326 | |
1327 | // Ring buffer based implementation for all Types sizeof(T) > sizeof(void*) |
1328 | + |
1329 | +// An implementation of ControlValueAtomicBase for non-atomic types T. Uses a |
1330 | +// ring-buffer of ControlRingValues and a read pointer and write pointer to |
1331 | +// provide getValue()/setValue() methods which *sacrifice perfect consistency* |
1332 | +// for the benefit of wait-free read/write access to a value. |
1333 | template<typename T, bool ATOMIC = false> |
1334 | -class ControlObjectValue { |
1335 | +class ControlValueAtomicBase { |
1336 | public: |
1337 | - inline T getValue() { |
1338 | + inline T getValue() const { |
1339 | T value = T(); |
1340 | unsigned int index = (unsigned int)m_readIndex |
1341 | % (cRingSize); |
1342 | @@ -59,10 +70,10 @@ |
1343 | // We are here if |
1344 | // 1) there are more then cReaderSlotCnt reader (get) reading the same value or |
1345 | // 2) the formerly current value is locked by a writer |
1346 | - // Case 1 does not happen because we have enough (0x7fffffff) reader slots. |
1347 | + // Case 1 does not happen because we have enough (0x7fffffff) reader slots. |
1348 | // Case 2 happens when the a reader is delayed after reading the |
1349 | - // m_currentIndex and in the mean while a reader locks the formaly current value |
1350 | - // because it has written cRingSize times. Reading the less recent value will fix |
1351 | + // m_currentIndex and in the mean while a reader locks the formaly current value |
1352 | + // because it has written cRingSize times. Reading the less recent value will fix |
1353 | // it because it is now actualy the current value. |
1354 | index = (index - 1) % (cRingSize); |
1355 | } |
1356 | @@ -85,7 +96,7 @@ |
1357 | } |
1358 | |
1359 | protected: |
1360 | - ControlObjectValue() |
1361 | + ControlValueAtomicBase() |
1362 | : m_readIndex(0), |
1363 | m_writeIndex(1) { |
1364 | Q_ASSERT((std::numeric_limits<unsigned int>::max() % cRingSize) == (cRingSize - 1)); |
1365 | @@ -94,16 +105,18 @@ |
1366 | private: |
1367 | // In worst case, each reader can consume a reader slot from a different ring element. |
1368 | // In this case there is still one ring element available for writing. |
1369 | - ControlObjectRingValue<T> m_ring[cRingSize]; |
1370 | + ControlRingValue<T> m_ring[cRingSize]; |
1371 | QAtomicInt m_readIndex; |
1372 | QAtomicInt m_writeIndex; |
1373 | }; |
1374 | |
1375 | -// Specialized Template for atomic types. |
1376 | +// Specialized template for types that are deemed to be atomic on the target |
1377 | +// architecture. Instead of using a read/write ring to guarantee atomicity, |
1378 | +// direct assignment/read of an aligned member variable is used. |
1379 | template<typename T> |
1380 | -class ControlObjectValue<T, true> { |
1381 | +class ControlValueAtomicBase<T, true> { |
1382 | public: |
1383 | - inline T getValue() { |
1384 | + inline T getValue() const { |
1385 | return m_value; |
1386 | } |
1387 | |
1388 | @@ -112,8 +125,8 @@ |
1389 | } |
1390 | |
1391 | protected: |
1392 | - ControlObjectValue() |
1393 | - : m_value(T()) { |
1394 | + ControlValueAtomicBase() |
1395 | + : m_value(T()) { |
1396 | } |
1397 | |
1398 | private: |
1399 | @@ -126,20 +139,19 @@ |
1400 | #endif |
1401 | }; |
1402 | |
1403 | -// This is a proxy Template to select the native atomic or the ring buffer |
1404 | -// Implementation depending on the target architecture |
1405 | -// Note: Qt does not support templates for signal and slots |
1406 | -// So the typified ControlObject has to handle the Event Queue connections |
1407 | +// ControlValueAtomic is a wrapper around ControlValueAtomicBase which uses the |
1408 | +// sizeof(T) to determine which underlying implementation of |
1409 | +// ControlValueAtomicBase to use. For types where sizeof(T) <= sizeof(void*), |
1410 | +// the specialized implementation of ControlValueAtomicBase for types that are |
1411 | +// atomic on the architecture is used. |
1412 | template<typename T> |
1413 | -class ControlObjectBase |
1414 | - : public ControlObjectValue<T, sizeof(T) <= sizeof(void*)> { |
1415 | +class ControlValueAtomic |
1416 | + : public ControlValueAtomicBase<T, sizeof(T) <= sizeof(void*)> { |
1417 | public: |
1418 | |
1419 | - ControlObjectBase() |
1420 | - : ControlObjectValue<T, sizeof(T) <= sizeof(void*)>() { |
1421 | + ControlValueAtomic() |
1422 | + : ControlValueAtomicBase<T, sizeof(T) <= sizeof(void*)>() { |
1423 | } |
1424 | }; |
1425 | |
1426 | - |
1427 | -#endif // CONTROLOBJECTBASE_H_ |
1428 | - |
1429 | +#endif /* CONTROLVALUE_H */ |
1430 | |
1431 | === removed file 'mixxx/src/controlbeat.cpp' |
1432 | --- mixxx/src/controlbeat.cpp 2013-03-13 16:31:06 +0000 |
1433 | +++ mixxx/src/controlbeat.cpp 1970-01-01 00:00:00 +0000 |
1434 | @@ -1,83 +0,0 @@ |
1435 | -/*************************************************************************** |
1436 | - controlbeat.cpp - description |
1437 | - ------------------- |
1438 | - begin : Mon Apr 7 2003 |
1439 | - copyright : (C) 2003 by Tue & Ken Haste Andersen |
1440 | - email : haste@diku.dk |
1441 | -***************************************************************************/ |
1442 | - |
1443 | -/*************************************************************************** |
1444 | -* * |
1445 | -* This program is free software; you can redistribute it and/or modify * |
1446 | -* it under the terms of the GNU General Public License as published by * |
1447 | -* the Free Software Foundation; either version 2 of the License, or * |
1448 | -* (at your option) any later version. * |
1449 | -* * |
1450 | -***************************************************************************/ |
1451 | - |
1452 | -#include "controlbeat.h" |
1453 | - |
1454 | -ControlBeat::ControlBeat(ConfigKey key, bool bMidiSimulateLatching) |
1455 | - : ControlObject(key), |
1456 | - m_bMidiSimulateLatching(bMidiSimulateLatching), |
1457 | - m_bPressed(false), |
1458 | - m_iValidPresses(0) { |
1459 | - |
1460 | - time.start(); |
1461 | - // Filter buffer |
1462 | - buffer = new CSAMPLE[filterLength]; |
1463 | - for (int i = 0; i < filterLength; i++) { |
1464 | - buffer[i] = 0.; |
1465 | - } |
1466 | -} |
1467 | - |
1468 | -ControlBeat::~ControlBeat() |
1469 | -{ |
1470 | - delete [] buffer; |
1471 | -} |
1472 | - |
1473 | -void ControlBeat::setValueFromMidi(MidiOpCode o, double v) |
1474 | -{ |
1475 | - Q_UNUSED(o); |
1476 | - Q_UNUSED(v); |
1477 | - if (!m_bPressed || !m_bMidiSimulateLatching) |
1478 | - { |
1479 | - beatTap(); |
1480 | - m_bPressed = true; |
1481 | - } |
1482 | - else |
1483 | - m_bPressed = false; |
1484 | -} |
1485 | - |
1486 | -void ControlBeat::setValueFromThread(double dValue) { |
1487 | - if (dValue > 0) { |
1488 | - beatTap(); |
1489 | - } |
1490 | -} |
1491 | - |
1492 | -void ControlBeat::beatTap() |
1493 | -{ |
1494 | - int elapsed = time.restart(); |
1495 | - |
1496 | - if (elapsed <= maxInterval) { |
1497 | - // Move back in filter one sample |
1498 | - for (int i = filterLength-1; i > 0; i--) |
1499 | - buffer[i] = buffer[i-1]; |
1500 | - |
1501 | - buffer[0] = 1000.*(60./elapsed); |
1502 | - if (buffer[0] > maxBPM) |
1503 | - buffer[0] = maxBPM; |
1504 | - |
1505 | - m_iValidPresses++; |
1506 | - if (m_iValidPresses > filterLength) |
1507 | - m_iValidPresses = filterLength; |
1508 | - |
1509 | - double temp = 0.; |
1510 | - for (int i = 0; i < m_iValidPresses; ++i) |
1511 | - temp += buffer[i]; |
1512 | - temp /= m_iValidPresses; |
1513 | - set(temp); |
1514 | - } else { |
1515 | - m_iValidPresses = 0; |
1516 | - } |
1517 | -} |
1518 | |
1519 | === removed file 'mixxx/src/controlbeat.h' |
1520 | --- mixxx/src/controlbeat.h 2012-03-17 17:42:44 +0000 |
1521 | +++ mixxx/src/controlbeat.h 1970-01-01 00:00:00 +0000 |
1522 | @@ -1,59 +0,0 @@ |
1523 | -/*************************************************************************** |
1524 | - controlbeat.h - description |
1525 | - ------------------- |
1526 | - begin : Mon Apr 7 2003 |
1527 | - copyright : (C) 2003 by Tue & Ken Haste Andersen |
1528 | - email : haste@diku.dk |
1529 | - ***************************************************************************/ |
1530 | - |
1531 | -/*************************************************************************** |
1532 | - * * |
1533 | - * This program is free software; you can redistribute it and/or modify * |
1534 | - * it under the terms of the GNU General Public License as published by * |
1535 | - * the Free Software Foundation; either version 2 of the License, or * |
1536 | - * (at your option) any later version. * |
1537 | - * * |
1538 | - ***************************************************************************/ |
1539 | - |
1540 | -#ifndef CONTROLBEAT_H |
1541 | -#define CONTROLBEAT_H |
1542 | - |
1543 | -#include "controlobject.h" |
1544 | -#include "configobject.h" |
1545 | -#include "defs.h" |
1546 | -#include <qdatetime.h> |
1547 | - |
1548 | -/** |
1549 | - * Takes impulses as input, and convert it to a BPM measure. |
1550 | - * |
1551 | - *@author Tue & Ken Haste Andersen |
1552 | - */ |
1553 | - |
1554 | -/** Minimum allowed Beat per minute (BPM) */ |
1555 | -const int minBPM = 30; |
1556 | -/** Maximum allowed bpm */ |
1557 | -const int maxBPM = 240; |
1558 | -/** Maximum allowed interval between beats in milli seconds (calculated from minBPM) */ |
1559 | -const int maxInterval = (int)(1000.*(60./(CSAMPLE)minBPM)); |
1560 | -/** Filter length */ |
1561 | -const int filterLength = 5; |
1562 | - |
1563 | -class ControlBeat : public ControlObject { |
1564 | - public: |
1565 | - ControlBeat(ConfigKey key, bool bMidiSimulateLatching=false); |
1566 | - virtual ~ControlBeat(); |
1567 | - |
1568 | - protected: |
1569 | - void setValueFromMidi(MidiOpCode o, double v); |
1570 | - void setValueFromThread(double dValue); |
1571 | - private: |
1572 | - void beatTap(); |
1573 | - |
1574 | - QTime time; |
1575 | - CSAMPLE *buffer; |
1576 | - bool m_bMidiSimulateLatching; |
1577 | - bool m_bPressed; |
1578 | - int m_iValidPresses; |
1579 | -}; |
1580 | - |
1581 | -#endif |
1582 | |
1583 | === modified file 'mixxx/src/controllers/controllerengine.cpp' |
1584 | --- mixxx/src/controllers/controllerengine.cpp 2013-05-01 21:53:11 +0000 |
1585 | +++ mixxx/src/controllers/controllerengine.cpp 2013-05-16 01:44:29 +0000 |
1586 | @@ -640,8 +640,11 @@ |
1587 | |
1588 | ControlObjectThread *cot = getControlObjectThread(group, name); |
1589 | |
1590 | - if (cot != NULL && !m_st.ignore(cot->getControlObject(), newValue)) { |
1591 | - cot->slotSet(newValue); |
1592 | + if (cot != NULL) { |
1593 | + ControlObject* pControl = ControlObject::getControl(cot->getKey()); |
1594 | + if (pControl && !m_st.ignore(pControl, newValue)) { |
1595 | + cot->slotSet(newValue); |
1596 | + } |
1597 | } |
1598 | } |
1599 | |
1600 | @@ -812,12 +815,7 @@ |
1601 | return; |
1602 | } |
1603 | |
1604 | - ControlObject* pSenderCO = senderCOT->getControlObject(); |
1605 | - if (pSenderCO == NULL) { |
1606 | - qWarning() << "ControllerEngine::slotValueChanged() The sender's CO is NULL."; |
1607 | - return; |
1608 | - } |
1609 | - ConfigKey key = pSenderCO->getKey(); |
1610 | + ConfigKey key = senderCOT->getKey(); |
1611 | |
1612 | //qDebug() << "[Controller]: SlotValueChanged" << key.group << key.item; |
1613 | |
1614 | |
1615 | === modified file 'mixxx/src/controllers/midi/midicontroller.cpp' |
1616 | --- mixxx/src/controllers/midi/midicontroller.cpp 2013-05-01 21:53:11 +0000 |
1617 | +++ mixxx/src/controllers/midi/midicontroller.cpp 2013-05-16 01:44:29 +0000 |
1618 | @@ -165,6 +165,58 @@ |
1619 | } |
1620 | } |
1621 | |
1622 | +QString formatMidiMessage(unsigned char status, unsigned char control, unsigned char value, |
1623 | + unsigned char channel, unsigned char opCode) { |
1624 | + switch (opCode) { |
1625 | + case MIDI_PITCH_BEND: |
1626 | + return QString("MIDI status 0x%1: pitch bend ch %2, value 0x%3") |
1627 | + .arg(QString::number(status, 16).toUpper(), |
1628 | + QString::number(channel+1, 10), |
1629 | + QString::number((value << 7) | control, 16).toUpper().rightJustified(4,'0')); |
1630 | + case MIDI_SONG_POS: |
1631 | + return QString("MIDI status 0x%1: song position 0x%2") |
1632 | + .arg(QString::number(status, 16).toUpper(), |
1633 | + QString::number((value << 7) | control, 16).toUpper().rightJustified(4,'0')); |
1634 | + case MIDI_PROGRAM_CH: |
1635 | + case MIDI_CH_AFTERTOUCH: |
1636 | + return QString("MIDI status 0x%1 (ch %2, opcode 0x%3), value 0x%4") |
1637 | + .arg(QString::number(status, 16).toUpper(), |
1638 | + QString::number(channel+1, 10), |
1639 | + QString::number((status & 255)>>4, 16).toUpper(), |
1640 | + QString::number(control, 16).toUpper().rightJustified(2,'0')); |
1641 | + case MIDI_SONG: |
1642 | + return QString("MIDI status 0x%1: select song #%2") |
1643 | + .arg(QString::number(status, 16).toUpper(), |
1644 | + QString::number(control+1, 10)); |
1645 | + case MIDI_NOTE_OFF: |
1646 | + case MIDI_NOTE_ON: |
1647 | + case MIDI_AFTERTOUCH: |
1648 | + case MIDI_CC: |
1649 | + return QString("MIDI status 0x%1 (ch %2, opcode 0x%3), ctrl 0x%4, val 0x%5") |
1650 | + .arg(QString::number(status, 16).toUpper(), |
1651 | + QString::number(channel+1, 10), |
1652 | + QString::number((status & 255)>>4, 16).toUpper(), |
1653 | + QString::number(control, 16).toUpper().rightJustified(2,'0'), |
1654 | + QString::number(value, 16).toUpper().rightJustified(2,'0')); |
1655 | + default: |
1656 | + return QString("MIDI status 0x%1") |
1657 | + .arg(QString::number(status, 16).toUpper()); |
1658 | + } |
1659 | +} |
1660 | + |
1661 | +bool isMessageTwoBytes(unsigned char opCode) { |
1662 | + switch (opCode) { |
1663 | + case MIDI_SONG: |
1664 | + case MIDI_NOTE_OFF: |
1665 | + case MIDI_NOTE_ON: |
1666 | + case MIDI_AFTERTOUCH: |
1667 | + case MIDI_CC: |
1668 | + return true; |
1669 | + default: |
1670 | + return false; |
1671 | + } |
1672 | +} |
1673 | + |
1674 | void MidiController::receive(unsigned char status, unsigned char control, |
1675 | unsigned char value) { |
1676 | unsigned char channel = status & 0x0F; |
1677 | @@ -173,57 +225,10 @@ |
1678 | opCode = status; |
1679 | } |
1680 | |
1681 | - QString message; |
1682 | - bool twoBytes = true; |
1683 | - |
1684 | - switch (opCode) { |
1685 | - case MIDI_PITCH_BEND: |
1686 | - twoBytes = false; |
1687 | - message = QString("MIDI status 0x%1: pitch bend ch %2, value 0x%3") |
1688 | - .arg(QString::number(status, 16).toUpper(), |
1689 | - QString::number(channel+1, 10), |
1690 | - QString::number((value << 7) | control, 16).toUpper().rightJustified(4,'0')); |
1691 | - break; |
1692 | - case MIDI_SONG_POS: |
1693 | - twoBytes = false; |
1694 | - message = QString("MIDI status 0x%1: song position 0x%2") |
1695 | - .arg(QString::number(status, 16).toUpper(), |
1696 | - QString::number((value << 7) | control, 16).toUpper().rightJustified(4,'0')); |
1697 | - break; |
1698 | - case MIDI_PROGRAM_CH: |
1699 | - case MIDI_CH_AFTERTOUCH: |
1700 | - twoBytes = false; |
1701 | - message = QString("MIDI status 0x%1 (ch %2, opcode 0x%3), value 0x%4") |
1702 | - .arg(QString::number(status, 16).toUpper(), |
1703 | - QString::number(channel+1, 10), |
1704 | - QString::number((status & 255)>>4, 16).toUpper(), |
1705 | - QString::number(control, 16).toUpper().rightJustified(2,'0')); |
1706 | - break; |
1707 | - case MIDI_SONG: |
1708 | - message = QString("MIDI status 0x%1: select song #%2") |
1709 | - .arg(QString::number(status, 16).toUpper(), |
1710 | - QString::number(control+1, 10)); |
1711 | - break; |
1712 | - case MIDI_NOTE_OFF: |
1713 | - case MIDI_NOTE_ON: |
1714 | - case MIDI_AFTERTOUCH: |
1715 | - case MIDI_CC: |
1716 | - message = QString("MIDI status 0x%1 (ch %2, opcode 0x%3), ctrl 0x%4, val 0x%5") |
1717 | - .arg(QString::number(status, 16).toUpper(), |
1718 | - QString::number(channel+1, 10), |
1719 | - QString::number((status & 255)>>4, 16).toUpper(), |
1720 | - QString::number(control, 16).toUpper().rightJustified(2,'0'), |
1721 | - QString::number(value, 16).toUpper().rightJustified(2,'0')); |
1722 | - break; |
1723 | - default: |
1724 | - twoBytes = false; |
1725 | - message = QString("MIDI status 0x%1") |
1726 | - .arg(QString::number(status, 16).toUpper()); |
1727 | - break; |
1728 | - } |
1729 | + bool twoBytes = isMessageTwoBytes(opCode); |
1730 | |
1731 | if (debugging()) { |
1732 | - qDebug() << message; |
1733 | + qDebug() << formatMidiMessage(status, control, value, channel, opCode); |
1734 | } |
1735 | |
1736 | //if (m_bReceiveInhibit) return; |
1737 | @@ -265,16 +270,12 @@ |
1738 | //Reset the saved control. |
1739 | setControlToLearn(MixxxControl()); |
1740 | |
1741 | - QString message = "error"; |
1742 | - if (twoBytes) { |
1743 | - message = QString("0x%1 0x%2") |
1744 | - .arg(QString::number(mappingKey.status, 16).toUpper(), |
1745 | - QString::number(mappingKey.control, 16).toUpper() |
1746 | - .rightJustified(2,'0')); |
1747 | - } else { |
1748 | - message = QString("0x%1") |
1749 | - .arg(QString::number(mappingKey.status, 16).toUpper()); |
1750 | - } |
1751 | + QString message = twoBytes ? QString("0x%1 0x%2") |
1752 | + .arg(QString::number(mappingKey.status, 16).toUpper(), |
1753 | + QString::number(mappingKey.control, 16).toUpper() |
1754 | + .rightJustified(2,'0')) : |
1755 | + QString("0x%1") |
1756 | + .arg(QString::number(mappingKey.status, 16).toUpper()); |
1757 | emit(learnedMessage(message)); |
1758 | } |
1759 | } |
1760 | @@ -333,7 +334,7 @@ |
1761 | |
1762 | // computeValue not (yet) done on pitch messages because it all assumes 7-bit numbers |
1763 | } else { |
1764 | - double currMixxxControlValue = p->GetMidiValue(); |
1765 | + double currMixxxControlValue = p->getValueToMidi(); |
1766 | newValue = computeValue(options, currMixxxControlValue, value); |
1767 | } |
1768 | |
1769 | @@ -355,7 +356,7 @@ |
1770 | return; |
1771 | } |
1772 | } |
1773 | - p->setValueFromThread(newValue); |
1774 | + p->setValueFromThread(newValue, NULL); |
1775 | } else { |
1776 | if (options.soft_takeover) { |
1777 | if (m_st.ignore(p, newValue, true)) { |
1778 | @@ -456,17 +457,20 @@ |
1779 | return _newmidivalue; |
1780 | } |
1781 | |
1782 | -void MidiController::receive(QByteArray data) { |
1783 | - int length = data.size(); |
1784 | - QString message = QString("%1: %2 bytes: [").arg(getName()).arg(length); |
1785 | - for (int i = 0; i < length; ++i) { |
1786 | +QString formatSysexMessage(QString controllerName, const QByteArray& data) { |
1787 | + QString message = QString("%1: %2 bytes: [").arg(controllerName).arg(data.size()); |
1788 | + for (int i = 0; i < data.size(); ++i) { |
1789 | message += QString("%1%2").arg( |
1790 | QString("%1").arg((unsigned char)(data.at(i)), 2, 16, QChar('0')).toUpper(), |
1791 | - QString("%1").arg((i < (length-1)) ? ' ' : ']')); |
1792 | + QString("%1").arg((i < (data.size()-1)) ? ' ' : ']')); |
1793 | } |
1794 | + return message; |
1795 | +} |
1796 | |
1797 | - if (debugging()) |
1798 | - qDebug() << message; |
1799 | +void MidiController::receive(QByteArray data) { |
1800 | + if (debugging()) { |
1801 | + qDebug() << formatSysexMessage(getName(), data); |
1802 | + } |
1803 | |
1804 | //if (m_bReceiveInhibit) return; |
1805 | |
1806 | @@ -494,7 +498,7 @@ |
1807 | setControlToLearn(MixxxControl()); |
1808 | |
1809 | QString message = QString("0x%1") |
1810 | - .arg(QString::number(mappingKey.status, 16).toUpper()); |
1811 | + .arg(QString::number(mappingKey.status, 16).toUpper()); |
1812 | emit(learnedMessage(message)); |
1813 | } |
1814 | // Don't process MIDI messages when learning |
1815 | @@ -523,7 +527,8 @@ |
1816 | } |
1817 | return; |
1818 | } |
1819 | - qWarning() << "MidiController: No script function specified for" << message; |
1820 | + qWarning() << "MidiController: No script function specified for" |
1821 | + << formatSysexMessage(getName(), data); |
1822 | } |
1823 | |
1824 | void MidiController::sendShortMsg(unsigned char status, unsigned char byte1, unsigned char byte2) { |
1825 | |
1826 | === modified file 'mixxx/src/controllers/midi/midioutputhandler.cpp' |
1827 | --- mixxx/src/controllers/midi/midioutputhandler.cpp 2013-03-13 16:31:06 +0000 |
1828 | +++ mixxx/src/controllers/midi/midioutputhandler.cpp 2013-05-16 01:44:29 +0000 |
1829 | @@ -6,10 +6,11 @@ |
1830 | * |
1831 | */ |
1832 | |
1833 | +#include <QtDebug> |
1834 | + |
1835 | #include "controllers/midi/midioutputhandler.h" |
1836 | #include "controllers/midi/midicontroller.h" |
1837 | - |
1838 | -#include <QDebug> |
1839 | +#include "controlobject.h" |
1840 | |
1841 | MidiOutputHandler::MidiOutputHandler(QString group, QString key, |
1842 | MidiController *controller, |
1843 | @@ -25,32 +26,24 @@ |
1844 | m_on(on), |
1845 | m_off(off), |
1846 | m_lastVal(0) { |
1847 | + connect(&m_cobj, SIGNAL(valueChanged(double)), |
1848 | + this, SLOT(controlChanged(double))); |
1849 | } |
1850 | |
1851 | MidiOutputHandler::~MidiOutputHandler() { |
1852 | - if (m_cobj != NULL) { |
1853 | - ConfigKey cKey = m_cobj->getKey(); |
1854 | - if (m_pController->debugging()) { |
1855 | - qDebug() << QString("Destroying static MIDI output handler on %1 for %2,%3") |
1856 | - .arg(m_pController->getName(), cKey.group, cKey.item); |
1857 | - } |
1858 | + ConfigKey cKey = m_cobj.getKey(); |
1859 | + if (m_pController->debugging()) { |
1860 | + qDebug() << QString("Destroying static MIDI output handler on %1 for %2,%3") |
1861 | + .arg(m_pController->getName(), cKey.group, cKey.item); |
1862 | } |
1863 | } |
1864 | |
1865 | bool MidiOutputHandler::validate() { |
1866 | - if (m_cobj == NULL) { |
1867 | - return false; |
1868 | - } |
1869 | - connect(m_cobj, SIGNAL(valueChanged(double)), |
1870 | - this, SLOT(controlChanged(double))); |
1871 | - return true; |
1872 | + return m_cobj.valid(); |
1873 | } |
1874 | |
1875 | void MidiOutputHandler::update() { |
1876 | - if (m_cobj == NULL) { |
1877 | - return; |
1878 | - } |
1879 | - controlChanged(m_cobj->get()); |
1880 | + controlChanged(m_cobj.get()); |
1881 | } |
1882 | |
1883 | void MidiOutputHandler::controlChanged(double value) { |
1884 | |
1885 | === modified file 'mixxx/src/controllers/midi/midioutputhandler.h' |
1886 | --- mixxx/src/controllers/midi/midioutputhandler.h 2012-04-24 05:51:32 +0000 |
1887 | +++ mixxx/src/controllers/midi/midioutputhandler.h 2013-05-16 01:44:29 +0000 |
1888 | @@ -11,7 +11,7 @@ |
1889 | #ifndef MIDIOUTPUTHANDLER_H |
1890 | #define MIDIOUTPUTHANDLER_H |
1891 | |
1892 | -#include "controlobject.h" |
1893 | +#include "controlobjectthread.h" |
1894 | |
1895 | class MidiController; // forward declaration |
1896 | |
1897 | @@ -32,7 +32,7 @@ |
1898 | |
1899 | private: |
1900 | MidiController* m_pController; |
1901 | - ControlObject* m_cobj; |
1902 | + ControlObjectThread m_cobj; |
1903 | float m_min; |
1904 | float m_max; |
1905 | unsigned char m_status; |
1906 | |
1907 | === modified file 'mixxx/src/controllers/softtakeover.cpp' |
1908 | --- mixxx/src/controllers/softtakeover.cpp 2013-04-27 22:06:33 +0000 |
1909 | +++ mixxx/src/controllers/softtakeover.cpp 2013-05-16 01:44:29 +0000 |
1910 | @@ -79,7 +79,7 @@ |
1911 | threshold = scaleFactor*(threshold/128.0f); |
1912 | } |
1913 | |
1914 | - double currentValue = midiVal ? control->GetMidiValue() : control->get(); |
1915 | + double currentValue = midiVal ? control->getValueToMidi() : control->get(); |
1916 | double difference = currentValue - newValue; |
1917 | double prevDiff = 0; |
1918 | bool sameSide = false; |
1919 | |
1920 | === modified file 'mixxx/src/controllinpotmeter.cpp' |
1921 | --- mixxx/src/controllinpotmeter.cpp 2013-03-13 16:31:06 +0000 |
1922 | +++ mixxx/src/controllinpotmeter.cpp 2013-05-16 01:44:29 +0000 |
1923 | @@ -1,34 +1,15 @@ |
1924 | #include "controllinpotmeter.h" |
1925 | #include "defs.h" |
1926 | |
1927 | - |
1928 | // This control has a linear link between the m_dValue and the Midi Value |
1929 | // limitation: m_dMaxValue represents the midi value of 128 and is never reached |
1930 | ControlLinPotmeter::ControlLinPotmeter(ConfigKey key, double dMinValue, double dMaxValue) : |
1931 | ControlPotmeter(key, dMinValue, dMaxValue) { |
1932 | - |
1933 | -} |
1934 | - |
1935 | -double ControlLinPotmeter::getValueToWidget(double dValue) { |
1936 | - double out = (dValue - m_dMinValue) / m_dValueRange; |
1937 | - return math_min(out * 128, 127); |
1938 | -} |
1939 | - |
1940 | -double ControlLinPotmeter::GetMidiValue() { |
1941 | - double out = get(); |
1942 | - out = (out - m_dMinValue) / m_dValueRange; |
1943 | - return math_min(out * 128, 127); |
1944 | -} |
1945 | - |
1946 | -double ControlLinPotmeter::getValueFromWidget(double dValue) { |
1947 | - double out = dValue / 128; |
1948 | - return m_dMinValue + out * m_dValueRange; |
1949 | -} |
1950 | - |
1951 | -void ControlLinPotmeter::setValueFromMidi(MidiOpCode o, double v) { |
1952 | - Q_UNUSED(o); |
1953 | - double out = v / 128; |
1954 | - set(m_dMinValue + out * m_dValueRange); |
1955 | + if (m_pControl) { |
1956 | + ControlNumericBehavior* pOldBehavior = m_pControl->setBehavior( |
1957 | + new ControlLinPotmeterBehavior(dMinValue, dMaxValue)); |
1958 | + delete pOldBehavior; |
1959 | + } |
1960 | } |
1961 | |
1962 | |
1963 | |
1964 | === modified file 'mixxx/src/controllinpotmeter.h' |
1965 | --- mixxx/src/controllinpotmeter.h 2012-12-22 14:07:45 +0000 |
1966 | +++ mixxx/src/controllinpotmeter.h 2013-05-16 01:44:29 +0000 |
1967 | @@ -3,19 +3,10 @@ |
1968 | |
1969 | #include "controlpotmeter.h" |
1970 | |
1971 | -class ControlLinPotmeter : public ControlPotmeter |
1972 | -{ |
1973 | +class ControlLinPotmeter : public ControlPotmeter { |
1974 | Q_OBJECT |
1975 | public: |
1976 | - |
1977 | ControlLinPotmeter(ConfigKey key, double dMinValue=0.0, double dMaxValue=1.0); |
1978 | - |
1979 | - double getValueToWidget(double dValue); |
1980 | - double GetMidiValue(); |
1981 | - double getValueFromWidget(double dValue); |
1982 | - |
1983 | - protected: |
1984 | - void setValueFromMidi(MidiOpCode o, double v); |
1985 | }; |
1986 | |
1987 | #endif // CONTROLLINPOTMETER_H |
1988 | |
1989 | === modified file 'mixxx/src/controllogpotmeter.cpp' |
1990 | --- mixxx/src/controllogpotmeter.cpp 2013-03-13 16:31:06 +0000 |
1991 | +++ mixxx/src/controllogpotmeter.cpp 2013-05-16 01:44:29 +0000 |
1992 | @@ -15,14 +15,8 @@ |
1993 | * * |
1994 | ***************************************************************************/ |
1995 | |
1996 | -#include <math.h> |
1997 | #include "controllogpotmeter.h" |
1998 | |
1999 | -#define maxPosition 127 |
2000 | -#define minPosition 0 |
2001 | -#define middlePosition ((maxPosition-minPosition)/2) |
2002 | -#define positionrange (maxPosition-minPosition) |
2003 | - |
2004 | /* -------- ------------------------------------------------------ |
2005 | Purpose: Creates a new logarithmic potmeter, where the value is |
2006 | given by: |
2007 | @@ -41,72 +35,13 @@ |
2008 | ControlLogpotmeter::ControlLogpotmeter(ConfigKey key, double dMaxValue) |
2009 | : ControlPotmeter(key, 0, dMaxValue) { |
2010 | // Override ControlPotmeters default value of 0.5 |
2011 | - m_dDefaultValue = 1.0; |
2012 | - set(m_dDefaultValue); |
2013 | - |
2014 | - if (m_dMaxValue == 1.) { |
2015 | - m_bTwoState = false; |
2016 | - m_fB1 = log10(2.)/maxPosition; |
2017 | - } else { |
2018 | - m_bTwoState = true; |
2019 | - m_fB1 = log10(2.)/middlePosition; |
2020 | - m_fB2 = log10(dMaxValue)/(maxPosition-middlePosition); |
2021 | - } |
2022 | -} |
2023 | - |
2024 | -double ControlLogpotmeter::getValueFromWidget(double dValue) |
2025 | -{ |
2026 | - double dResult = 0; |
2027 | - |
2028 | - // Calculate the value linearly: |
2029 | - if (!m_bTwoState) |
2030 | - { |
2031 | - dResult = pow(10., (double)(m_fB1*dValue)) - 1; |
2032 | - } |
2033 | - else |
2034 | - { |
2035 | - if (dValue <= middlePosition) |
2036 | - dResult = pow(10., m_fB1*dValue) - 1; |
2037 | - else |
2038 | - dResult = pow(10., m_fB2*(dValue - middlePosition)); |
2039 | - } |
2040 | - |
2041 | - //qDebug() << "Midi: " << dValue << " ValueFromWidget : " << m_dValue; |
2042 | - return dResult; |
2043 | -} |
2044 | - |
2045 | -double ControlLogpotmeter::getValueToWidget(double dValue) |
2046 | -{ |
2047 | - double pos; |
2048 | - |
2049 | - if (!m_bTwoState) |
2050 | - { |
2051 | - pos = log10(dValue+1)/m_fB1; |
2052 | - } |
2053 | - else |
2054 | - { |
2055 | - if (dValue > 1.) { |
2056 | - pos = log10(dValue) / m_fB2 + middlePosition; |
2057 | - } else { |
2058 | - pos = log10(dValue+1) / m_fB1; |
2059 | - } |
2060 | - } |
2061 | - //qDebug() << "GetValueToWidget : " << pos; |
2062 | - return pos; |
2063 | -} |
2064 | - |
2065 | -double ControlLogpotmeter::GetMidiValue() |
2066 | -{ |
2067 | - double midival = 0.; |
2068 | - |
2069 | - midival = getValueToWidget(get()); |
2070 | - // midival = 127.*(midival-m_dMinValue)/m_dValueRange |
2071 | - //qDebug() << "GetMidiValue : " << midival; |
2072 | - return midival; |
2073 | -} |
2074 | - |
2075 | -void ControlLogpotmeter::setValueFromMidi(MidiOpCode o, double v) { |
2076 | - Q_UNUSED(o); |
2077 | - set(getValueFromWidget(v)); |
2078 | + setDefaultValue(1.0); |
2079 | + set(1.0); |
2080 | + |
2081 | + if (m_pControl) { |
2082 | + ControlNumericBehavior* pOldBehavior = m_pControl->setBehavior( |
2083 | + new ControlLogpotmeterBehavior(dMaxValue)); |
2084 | + delete pOldBehavior; |
2085 | + } |
2086 | } |
2087 | |
2088 | |
2089 | === modified file 'mixxx/src/controllogpotmeter.h' |
2090 | --- mixxx/src/controllogpotmeter.h 2012-03-17 17:42:44 +0000 |
2091 | +++ mixxx/src/controllogpotmeter.h 2013-05-16 01:44:29 +0000 |
2092 | @@ -3,7 +3,7 @@ |
2093 | ------------------- |
2094 | begin : Wed Feb 20 2002 |
2095 | copyright : (C) 2002 by Tue and Ken Haste Andersen |
2096 | - email : |
2097 | + email : |
2098 | ***************************************************************************/ |
2099 | |
2100 | /*************************************************************************** |
2101 | @@ -26,28 +26,10 @@ |
2102 | *@author Tue and Ken Haste Andersen |
2103 | */ |
2104 | |
2105 | -class ControlLogpotmeter : public ControlPotmeter |
2106 | -{ |
2107 | +class ControlLogpotmeter : public ControlPotmeter { |
2108 | Q_OBJECT |
2109 | -public: |
2110 | + public: |
2111 | ControlLogpotmeter(ConfigKey key, double dMaxValue=5.); |
2112 | - |
2113 | - double getValueFromWidget(double dValue); |
2114 | - double getValueToWidget(double dValue); |
2115 | - |
2116 | - double GetMidiValue(); |
2117 | - |
2118 | - void setValueFromMidi(MidiOpCode o, double v); |
2119 | - |
2120 | -protected: |
2121 | - |
2122 | - // This is true, if the log potmeter is divided into two states, one from 0 to 1, and |
2123 | - // the second from 1 to m_dMaxValue. Two states is often used with knobs where the first |
2124 | - // half rotation is used to control a value between 0 and 1, and the second half between |
2125 | - // 1 and some bigger value. |
2126 | - bool m_bTwoState; |
2127 | - |
2128 | - double m_fB1, m_fB2; |
2129 | }; |
2130 | |
2131 | #endif |
2132 | |
2133 | === removed file 'mixxx/src/controlnull.cpp' |
2134 | --- mixxx/src/controlnull.cpp 2007-09-09 22:52:24 +0000 |
2135 | +++ mixxx/src/controlnull.cpp 1970-01-01 00:00:00 +0000 |
2136 | @@ -1,27 +0,0 @@ |
2137 | -/*************************************************************************** |
2138 | - controlnull.cpp - description |
2139 | - ------------------- |
2140 | - begin : Sat Jun 15 2002 |
2141 | - copyright : (C) 2002 by Tue & Ken Haste Andersen |
2142 | - email : haste@diku.dk |
2143 | -***************************************************************************/ |
2144 | - |
2145 | -/*************************************************************************** |
2146 | -* * |
2147 | -* This program is free software; you can redistribute it and/or modify * |
2148 | -* it under the terms of the GNU General Public License as published by * |
2149 | -* the Free Software Foundation; either version 2 of the License, or * |
2150 | -* (at your option) any later version. * |
2151 | -* * |
2152 | -***************************************************************************/ |
2153 | - |
2154 | -#include "controlnull.h" |
2155 | - |
2156 | -ControlNull::ControlNull() : ControlObject() |
2157 | -{ |
2158 | -} |
2159 | - |
2160 | -ControlNull::~ControlNull() |
2161 | -{ |
2162 | -} |
2163 | - |
2164 | |
2165 | === removed file 'mixxx/src/controlnull.h' |
2166 | --- mixxx/src/controlnull.h 2004-10-01 08:18:11 +0000 |
2167 | +++ mixxx/src/controlnull.h 1970-01-01 00:00:00 +0000 |
2168 | @@ -1,34 +0,0 @@ |
2169 | -/*************************************************************************** |
2170 | - controlnull.h - description |
2171 | - ------------------- |
2172 | - begin : Sat Jun 15 2002 |
2173 | - copyright : (C) 2002 by Tue & Ken Haste Andersen |
2174 | - email : haste@diku.dk |
2175 | - ***************************************************************************/ |
2176 | - |
2177 | -/*************************************************************************** |
2178 | - * * |
2179 | - * This program is free software; you can redistribute it and/or modify * |
2180 | - * it under the terms of the GNU General Public License as published by * |
2181 | - * the Free Software Foundation; either version 2 of the License, or * |
2182 | - * (at your option) any later version. * |
2183 | - * * |
2184 | - ***************************************************************************/ |
2185 | - |
2186 | -#ifndef CONTROLNULL_H |
2187 | -#define CONTROLNULL_H |
2188 | - |
2189 | -#include "controlobject.h" |
2190 | - |
2191 | -/** |
2192 | - *@author Tue & Ken Haste Andersen |
2193 | - */ |
2194 | - |
2195 | -class ControlNull : public ControlObject { |
2196 | - Q_OBJECT |
2197 | -public: |
2198 | - ControlNull(); |
2199 | - ~ControlNull(); |
2200 | -}; |
2201 | - |
2202 | -#endif |
2203 | |
2204 | === modified file 'mixxx/src/controlobject.cpp' |
2205 | --- mixxx/src/controlobject.cpp 2013-03-17 16:08:55 +0000 |
2206 | +++ mixxx/src/controlobject.cpp 2013-05-16 01:44:29 +0000 |
2207 | @@ -22,6 +22,7 @@ |
2208 | |
2209 | #include "controlobject.h" |
2210 | #include "controlevent.h" |
2211 | +#include "control/control.h" |
2212 | #include "util/stat.h" |
2213 | #include "util/timer.h" |
2214 | |
2215 | @@ -31,38 +32,30 @@ |
2216 | |
2217 | |
2218 | ControlObject::ControlObject() |
2219 | - : ControlObjectBase<double>(), |
2220 | - m_dDefaultValue(0), |
2221 | - m_bIgnoreNops(true) { |
2222 | - set(m_dDefaultValue); |
2223 | + : m_pControl(NULL) { |
2224 | } |
2225 | |
2226 | -ControlObject::ControlObject(ConfigKey key, bool bIgnoreNops, bool track) |
2227 | - : m_dDefaultValue(0), |
2228 | - m_key(key), |
2229 | - m_bIgnoreNops(bIgnoreNops), |
2230 | - m_bTrack(track), |
2231 | - m_trackKey("control " + m_key.group + "," + m_key.item), |
2232 | - m_trackType(Stat::UNSPECIFIED), |
2233 | - m_trackFlags(Stat::COUNT | Stat::SUM | Stat::AVERAGE | |
2234 | - Stat::SAMPLE_VARIANCE | Stat::MIN | Stat::MAX) { |
2235 | - set(m_dDefaultValue), |
2236 | +ControlObject::ControlObject(ConfigKey key, bool bIgnoreNops, bool bTrack) |
2237 | + : m_key(key), |
2238 | + m_pControl(ControlDoublePrivate::getControl(m_key, true, bIgnoreNops, bTrack)) { |
2239 | + connect(m_pControl, SIGNAL(valueChanged(double, QObject*)), |
2240 | + this, SLOT(privateValueChanged(double, QObject*)), |
2241 | + Qt::DirectConnection); |
2242 | + |
2243 | m_sqCOHashMutex.lock(); |
2244 | m_sqCOHash.insert(m_key, this); |
2245 | m_sqCOHashMutex.unlock(); |
2246 | - |
2247 | - if (m_bTrack) { |
2248 | - // TODO(rryan): Make configurable. |
2249 | - Stat::track(m_trackKey, static_cast<Stat::StatType>(m_trackType), |
2250 | - static_cast<Stat::ComputeFlags>(m_trackFlags), m_dDefaultValue); |
2251 | - } |
2252 | } |
2253 | |
2254 | -ControlObject::ControlObject(const QString& group, const QString& item, bool bIgnoreNops) |
2255 | - : m_dDefaultValue(0), |
2256 | - m_key(group, item), |
2257 | - m_bIgnoreNops(bIgnoreNops) { |
2258 | - set(m_dDefaultValue); |
2259 | +ControlObject::ControlObject(const QString& group, const QString& item, |
2260 | + bool bIgnoreNops, bool bTrack) |
2261 | + : m_key(group, item), |
2262 | + m_pControl(ControlDoublePrivate::getControl(m_key, true, bIgnoreNops, bTrack)) { |
2263 | + |
2264 | + connect(m_pControl, SIGNAL(valueChanged(double, QObject*)), |
2265 | + this, SLOT(privateValueChanged(double, QObject*)), |
2266 | + Qt::DirectConnection); |
2267 | + |
2268 | m_sqCOHashMutex.lock(); |
2269 | m_sqCOHash.insert(m_key, this); |
2270 | m_sqCOHashMutex.unlock(); |
2271 | @@ -72,16 +65,15 @@ |
2272 | m_sqCOHashMutex.lock(); |
2273 | m_sqCOHash.remove(m_key); |
2274 | m_sqCOHashMutex.unlock(); |
2275 | +} |
2276 | |
2277 | - ControlObjectThread * obj; |
2278 | - m_qProxyListMutex.lock(); |
2279 | - QListIterator<ControlObjectThread*> it(m_qProxyList); |
2280 | - while (it.hasNext()) |
2281 | - { |
2282 | - obj = it.next(); |
2283 | - obj->slotParentDead(); |
2284 | +void ControlObject::privateValueChanged(double dValue, QObject* pSetter) { |
2285 | + // Only emit valueChanged() if we did not originate this change. |
2286 | + if (pSetter != this) { |
2287 | + emit(valueChanged(dValue)); |
2288 | + } else { |
2289 | + emit(valueChangedFromEngine(dValue)); |
2290 | } |
2291 | - m_qProxyListMutex.unlock(); |
2292 | } |
2293 | |
2294 | /* |
2295 | @@ -114,19 +106,6 @@ |
2296 | } |
2297 | */ |
2298 | |
2299 | -void ControlObject::addProxy(ControlObjectThread * pControlObjectThread) |
2300 | -{ |
2301 | - m_qProxyListMutex.lock(); |
2302 | - m_qProxyList.append(pControlObjectThread); |
2303 | - m_qProxyListMutex.unlock(); |
2304 | -} |
2305 | - |
2306 | -void ControlObject::removeProxy(ControlObjectThread * pControlObjectThread) { |
2307 | - m_qProxyListMutex.lock(); |
2308 | - m_qProxyList.removeAll(pControlObjectThread); |
2309 | - m_qProxyListMutex.unlock(); |
2310 | -} |
2311 | - |
2312 | void ControlObject::getControls(QList<ControlObject*>* pControlList) { |
2313 | m_sqCOHashMutex.lock(); |
2314 | for (QHash<ConfigKey, ControlObject*>::const_iterator it = m_sqCOHash.begin(); |
2315 | @@ -148,68 +127,34 @@ |
2316 | return NULL; |
2317 | } |
2318 | |
2319 | -void ControlObject::setValueFromMidi(MidiOpCode o, double v) |
2320 | -{ |
2321 | - Q_UNUSED(o); |
2322 | - set(v); |
2323 | -} |
2324 | - |
2325 | -double ControlObject::GetMidiValue() |
2326 | -{ |
2327 | - return get(); |
2328 | -} |
2329 | - |
2330 | -void ControlObject::setValueFromThread(double dValue) |
2331 | -{ |
2332 | - set(dValue); |
2333 | -} |
2334 | - |
2335 | -void ControlObject::add(double dValue) |
2336 | -{ |
2337 | - if (m_bIgnoreNops && !dValue) { |
2338 | - return; |
2339 | - } |
2340 | - set(get() + dValue); |
2341 | -} |
2342 | - |
2343 | -void ControlObject::sub(double dValue) |
2344 | -{ |
2345 | - if (m_bIgnoreNops && !dValue) { |
2346 | - return; |
2347 | - } |
2348 | - set(get() - dValue); |
2349 | -} |
2350 | - |
2351 | -double ControlObject::getValueFromWidget(double v) |
2352 | -{ |
2353 | - return v; |
2354 | -} |
2355 | - |
2356 | -double ControlObject::getValueToWidget(double v) |
2357 | -{ |
2358 | - return v; |
2359 | -} |
2360 | - |
2361 | -double ControlObject::get() { |
2362 | - return getValue(); |
2363 | +void ControlObject::setValueFromMidi(MidiOpCode o, double v) { |
2364 | + if (m_pControl) { |
2365 | + m_pControl->setMidiParameter(o, v); |
2366 | + } |
2367 | +} |
2368 | + |
2369 | +double ControlObject::getValueToMidi() const { |
2370 | + return m_pControl ? m_pControl->getMidiParameter() : 0.0; |
2371 | +} |
2372 | + |
2373 | +void ControlObject::setValueFromThread(double dValue, QObject* pSender) { |
2374 | + if (m_pControl) { |
2375 | + m_pControl->set(dValue, pSender); |
2376 | + } |
2377 | +} |
2378 | + |
2379 | +double ControlObject::get() const { |
2380 | + return m_pControl ? m_pControl->get() : 0.0; |
2381 | } |
2382 | |
2383 | void ControlObject::reset() { |
2384 | - set(m_dDefaultValue); |
2385 | + if (m_pControl) { |
2386 | + m_pControl->reset(this); |
2387 | + } |
2388 | } |
2389 | |
2390 | -void ControlObject::set(const double& value, bool emitValueChanged) { |
2391 | - if (m_bIgnoreNops) { |
2392 | - if (get() == value) { |
2393 | - return; |
2394 | - } |
2395 | - } |
2396 | - setValue(value); |
2397 | - if (emitValueChanged) { |
2398 | - emit(valueChanged(value)); |
2399 | - if (m_bTrack) { |
2400 | - Stat::track(m_trackKey, static_cast<Stat::StatType>(m_trackType), |
2401 | - static_cast<Stat::ComputeFlags>(m_trackFlags), value); |
2402 | - } |
2403 | +void ControlObject::set(const double& value) { |
2404 | + if (m_pControl) { |
2405 | + m_pControl->set(value, this); |
2406 | } |
2407 | } |
2408 | |
2409 | === modified file 'mixxx/src/controlobject.h' |
2410 | --- mixxx/src/controlobject.h 2013-03-17 21:00:23 +0000 |
2411 | +++ mixxx/src/controlobject.h 2013-05-16 01:44:29 +0000 |
2412 | @@ -23,22 +23,19 @@ |
2413 | #include <QMutex> |
2414 | |
2415 | #include "configobject.h" |
2416 | -#include "controlobjectthread.h" |
2417 | #include "controllers/midi/midimessage.h" |
2418 | -#include "controlobjectbase.h" |
2419 | - |
2420 | -class QWidget; |
2421 | -class ConfigKey; |
2422 | - |
2423 | -class ControlObject |
2424 | - : public QObject, |
2425 | - private ControlObjectBase<double> { |
2426 | +#include "control/control.h" |
2427 | + |
2428 | +class ControlObject : public QObject { |
2429 | Q_OBJECT |
2430 | public: |
2431 | ControlObject(); |
2432 | - ControlObject(ConfigKey key, bool bIgnoreNops=true, bool track=false); |
2433 | - ControlObject(const QString& group, const QString& item, bool bIgnoreNops=true); |
2434 | + ControlObject(ConfigKey key, |
2435 | + bool bIgnoreNops=true, bool bTrack=false); |
2436 | + ControlObject(const QString& group, const QString& item, |
2437 | + bool bIgnoreNops=true, bool bTrack=false); |
2438 | virtual ~ControlObject(); |
2439 | + |
2440 | /** Returns a pointer to the ControlObject matching the given ConfigKey */ |
2441 | static ControlObject* getControl(const ConfigKey& key); |
2442 | static inline ControlObject* getControl(const QString& group, const QString& item) { |
2443 | @@ -49,61 +46,48 @@ |
2444 | // Adds all ControlObjects that currently exist to pControlList |
2445 | static void getControls(QList<ControlObject*>* pControlsList); |
2446 | |
2447 | - // Used to add a pointer to the corresponding ControlObjectThread of this ControlObject |
2448 | - void addProxy(ControlObjectThread *pControlObjectThread); |
2449 | - // To get rid of a proxy when the corresponding object is being deleted for example |
2450 | - void removeProxy(ControlObjectThread *pControlObjectThread); |
2451 | // Return the key of the object |
2452 | - inline ConfigKey getKey() { return m_key; } |
2453 | + inline ConfigKey getKey() const { return m_key; } |
2454 | // Returns the value of the ControlObject |
2455 | - double get(); |
2456 | + double get() const; |
2457 | // Sets the ControlObject value |
2458 | - void set(const double& value, bool emmitValueChanged = true); |
2459 | + void set(const double& value); |
2460 | // Sets the default value |
2461 | void reset(); |
2462 | - // Add to value |
2463 | - void add(double dValue); |
2464 | - // Subtract from value |
2465 | - void sub(double dValue); |
2466 | - // Return a ControlObject value, corresponding to the widget input value. |
2467 | - virtual double getValueFromWidget(double dValue); |
2468 | - // Return a widget value corresponding to the ControlObject input value. |
2469 | - virtual double getValueToWidget(double dValue); |
2470 | - // get value (range 0..127) |
2471 | - virtual double GetMidiValue(); |
2472 | - virtual void setDefaultValue(double dValue) { |
2473 | - m_dDefaultValue = dValue; |
2474 | + |
2475 | + inline void setDefaultValue(double dValue) { |
2476 | + if (m_pControl) { |
2477 | + m_pControl->setDefaultValue(dValue); |
2478 | + } |
2479 | } |
2480 | - virtual double defaultValue() const { |
2481 | - return m_dDefaultValue; |
2482 | + inline double defaultValue() const { |
2483 | + return m_pControl ? m_pControl->defaultValue() : 0.0; |
2484 | } |
2485 | |
2486 | signals: |
2487 | void valueChanged(double); |
2488 | + void valueChangedFromEngine(double); |
2489 | |
2490 | public: |
2491 | - // Called when a widget has changed value. |
2492 | + // DEPRECATED: Called to set the control value from the controller |
2493 | + // subsystem. |
2494 | virtual void setValueFromMidi(MidiOpCode o, double v); |
2495 | - // Called when another thread has changed value. |
2496 | - virtual void setValueFromThread(double dValue); |
2497 | + virtual double getValueToMidi() const; |
2498 | + // DEPRECATED: Called to set the control value from another thread. |
2499 | + virtual void setValueFromThread(double dValue, QObject* pSetter); |
2500 | |
2501 | protected: |
2502 | - double m_dDefaultValue; |
2503 | // Key of the object |
2504 | ConfigKey m_key; |
2505 | + ControlDoublePrivate* m_pControl; |
2506 | + |
2507 | + private slots: |
2508 | + void privateValueChanged(double value, QObject* pSetter); |
2509 | |
2510 | private: |
2511 | - // Whether to ignore set/add/sub()'s which would have no effect |
2512 | - bool m_bIgnoreNops; |
2513 | - // Whether to track value changes with the stats framework. |
2514 | - bool m_bTrack; |
2515 | - QString m_trackKey; |
2516 | - int m_trackType; |
2517 | - int m_trackFlags; |
2518 | - // List of associated proxy objects |
2519 | - QList<ControlObjectThread*> m_qProxyList; |
2520 | - // Mutex for the proxy list |
2521 | - QMutex m_qProxyListMutex; |
2522 | + inline bool ignoreNops() const { |
2523 | + return m_pControl ? m_pControl->ignoreNops() : true; |
2524 | + } |
2525 | |
2526 | // Hash of ControlObject instantiations |
2527 | static QHash<ConfigKey,ControlObject*> m_sqCOHash; |
2528 | @@ -111,5 +95,4 @@ |
2529 | static QMutex m_sqCOHashMutex; |
2530 | }; |
2531 | |
2532 | - |
2533 | #endif |
2534 | |
2535 | === modified file 'mixxx/src/controlobjectthread.cpp' |
2536 | --- mixxx/src/controlobjectthread.cpp 2013-03-14 14:57:52 +0000 |
2537 | +++ mixxx/src/controlobjectthread.cpp 2013-05-16 01:44:29 +0000 |
2538 | @@ -20,64 +20,63 @@ |
2539 | |
2540 | #include "controlobjectthread.h" |
2541 | #include "controlobject.h" |
2542 | +#include "control/control.h" |
2543 | |
2544 | ControlObjectThread::ControlObjectThread(ControlObject* pControlObject, QObject* pParent) |
2545 | : QObject(pParent), |
2546 | - m_pControlObject(pControlObject) { |
2547 | - // Register with the associated ControlObject |
2548 | - if (m_pControlObject != NULL) { |
2549 | - m_pControlObject->addProxy(this); |
2550 | - connect(m_pControlObject, SIGNAL(destroyed()), |
2551 | - this, SLOT(slotParentDead())); |
2552 | - connect(m_pControlObject, SIGNAL(valueChanged(double)), |
2553 | - this, SLOT(slotParentValueChanged(double))); |
2554 | - } |
2555 | - emitValueChanged(); |
2556 | + m_key(pControlObject ? pControlObject->getKey() : ConfigKey()), |
2557 | + m_pControl(NULL) { |
2558 | + if (pControlObject) { |
2559 | + m_pControl = ControlDoublePrivate::getControl(pControlObject->getKey(), false); |
2560 | + } |
2561 | + if (m_pControl) { |
2562 | + connect(m_pControl, SIGNAL(valueChanged(double, QObject*)), |
2563 | + this, SLOT(slotValueChanged(double, QObject*)), |
2564 | + Qt::DirectConnection); |
2565 | + } |
2566 | } |
2567 | |
2568 | ControlObjectThread::~ControlObjectThread() { |
2569 | - if (m_pControlObject) { |
2570 | - // Our parent is still around, make sure it doesn't send us any more events |
2571 | - m_pControlObject->removeProxy(this); |
2572 | - } |
2573 | +} |
2574 | + |
2575 | +bool ControlObjectThread::valid() const { |
2576 | + return m_pControl != NULL; |
2577 | } |
2578 | |
2579 | double ControlObjectThread::get() { |
2580 | - if (m_pControlObject) { |
2581 | - return m_pControlObject->get(); |
2582 | - } else { |
2583 | - return 0.0; |
2584 | - } |
2585 | - |
2586 | + return m_pControl ? m_pControl->get() : 0.0; |
2587 | } |
2588 | |
2589 | void ControlObjectThread::slotSet(double v) { |
2590 | - m_pControlObject->set(v); |
2591 | + set(v); |
2592 | +} |
2593 | + |
2594 | +void ControlObjectThread::set(double v) { |
2595 | + if (m_pControl) { |
2596 | + m_pControl->set(v, this); |
2597 | + } |
2598 | +} |
2599 | + |
2600 | +void ControlObjectThread::reset() { |
2601 | + if (m_pControl) { |
2602 | + // NOTE(rryan): This is important. The originator of this action does |
2603 | + // not know the resulting value so it makes sense that we should emit a |
2604 | + // general valueChanged() signal even though the change originated from |
2605 | + // us. For this reason, we provide NULL here so that the change is |
2606 | + // broadcast as valueChanged() and not valueChangedByThis(). |
2607 | + m_pControl->reset(NULL); |
2608 | + } |
2609 | } |
2610 | |
2611 | void ControlObjectThread::emitValueChanged() { |
2612 | emit(valueChanged(get())); |
2613 | } |
2614 | |
2615 | -void ControlObjectThread::add(double v) { |
2616 | - m_pControlObject->add(v); |
2617 | -} |
2618 | - |
2619 | -void ControlObjectThread::sub(double v) { |
2620 | - m_pControlObject->sub(v); |
2621 | -} |
2622 | - |
2623 | -void ControlObjectThread::slotParentDead() { |
2624 | - // Now we've got a chance of avoiding segfaults with judicious |
2625 | - // use of if(m_pControlObject) |
2626 | - m_pControlObject = NULL; |
2627 | -} |
2628 | - |
2629 | -void ControlObjectThread::slotParentValueChanged(double v) { |
2630 | - // This is base implementation of this function without scaling |
2631 | - emit(valueChanged(v)); |
2632 | -} |
2633 | - |
2634 | -ControlObject* ControlObjectThread::getControlObject() { |
2635 | - return m_pControlObject; |
2636 | +void ControlObjectThread::slotValueChanged(double v, QObject* pSetter) { |
2637 | + if (pSetter != this) { |
2638 | + // This is base implementation of this function without scaling |
2639 | + emit(valueChanged(v)); |
2640 | + } else { |
2641 | + emit(valueChangedByThis(v)); |
2642 | + } |
2643 | } |
2644 | |
2645 | === modified file 'mixxx/src/controlobjectthread.h' |
2646 | --- mixxx/src/controlobjectthread.h 2013-03-14 14:57:52 +0000 |
2647 | +++ mixxx/src/controlobjectthread.h 2013-05-16 01:44:29 +0000 |
2648 | @@ -24,6 +24,9 @@ |
2649 | #include <qwaitcondition.h> |
2650 | #include <QQueue> |
2651 | |
2652 | +#include "configobject.h" |
2653 | + |
2654 | +class ControlDoublePrivate; |
2655 | class ControlObject; |
2656 | |
2657 | class ControlObjectThread : public QObject { |
2658 | @@ -32,40 +35,41 @@ |
2659 | ControlObjectThread(ControlObject *pControlObject, QObject* pParent=NULL); |
2660 | virtual ~ControlObjectThread(); |
2661 | |
2662 | - /** Returns the value of the object. Thread safe, blocking */ |
2663 | - virtual double get(); |
2664 | - /** Setting the value from an external controller. This happen when a ControlObject has |
2665 | - * changed and its value is syncronized with this object. Thread safe, non blocking. Returns |
2666 | - * true if successful, otherwise false. Thread safe, non blocking. */ |
2667 | - virtual void add(double v); |
2668 | - /** Subtracts a value to the value property. Notification in a similar way |
2669 | - * to set. Thread safe, blocking. */ |
2670 | - virtual void sub(double v); |
2671 | /** Called from update(); */ |
2672 | void emitValueChanged(); |
2673 | |
2674 | - |
2675 | - // FIXME: Dangerous GED hack |
2676 | - ControlObject* getControlObject(); |
2677 | - |
2678 | -public slots: |
2679 | - /** The value is changed by the engine, and the corresponding ControlObject is updated. |
2680 | - * Thread safe, blocking. */ |
2681 | + inline ConfigKey getKey() const { |
2682 | + return m_key; |
2683 | + } |
2684 | + |
2685 | + // Returns the value of the object. Thread safe, non-blocking. |
2686 | + virtual double get(); |
2687 | + |
2688 | + bool valid() const; |
2689 | + |
2690 | + public slots: |
2691 | + // Set the control to a new value. Non-blocking. |
2692 | virtual void slotSet(double v); |
2693 | - |
2694 | - // The danger signal! This is for safety in wierd shutdown scenarios where the |
2695 | - // ControlObject dies to avoid segfaults. |
2696 | - void slotParentDead(); |
2697 | - |
2698 | - // Receives the Value from the parent and may scales the vale and re-emit it again |
2699 | - virtual void slotParentValueChanged(double v); |
2700 | - |
2701 | -signals: |
2702 | + // Sets the control value to v. Thread safe, non-blocking. |
2703 | + virtual void set(double v); |
2704 | + // Resets the control to its default value. Thread safe, non-blocking. |
2705 | + virtual void reset(); |
2706 | + |
2707 | + signals: |
2708 | void valueChanged(double); |
2709 | - |
2710 | -protected: |
2711 | - /// Pointer to corresponding ControlObject |
2712 | - ControlObject *m_pControlObject; |
2713 | + // This means that the control value has changed as a result of a mutation |
2714 | + // (set/add/sub/reset) originating from this object. |
2715 | + void valueChangedByThis(double); |
2716 | + |
2717 | + protected slots: |
2718 | + // Receives the value from the master control and re-emits either |
2719 | + // valueChanged(double) or valueChangedByThis(double) based on pSetter. |
2720 | + virtual void slotValueChanged(double v, QObject* pSetter); |
2721 | + |
2722 | + protected: |
2723 | + ConfigKey m_key; |
2724 | + // Pointer to connected control. |
2725 | + ControlDoublePrivate* m_pControl; |
2726 | }; |
2727 | |
2728 | #endif |
2729 | |
2730 | === modified file 'mixxx/src/controlobjectthreadmain.cpp' |
2731 | --- mixxx/src/controlobjectthreadmain.cpp 2013-03-14 00:13:02 +0000 |
2732 | +++ mixxx/src/controlobjectthreadmain.cpp 2013-05-16 01:44:29 +0000 |
2733 | @@ -13,6 +13,37 @@ |
2734 | ControlObjectThreadMain::ControlObjectThreadMain(ControlObject * pControlObject, QObject* pParent) |
2735 | : ControlObjectThread(pControlObject, pParent) { |
2736 | setObjectName("ControlObjectThreadMain"); |
2737 | -} |
2738 | - |
2739 | - |
2740 | + installEventFilter(this); |
2741 | +} |
2742 | + |
2743 | +bool ControlObjectThreadMain::eventFilter(QObject* o, QEvent* e) { |
2744 | + // Handle events |
2745 | + if (e && e->type() == MIXXXEVENT_CONTROL) { |
2746 | + ControlEvent * ce = (ControlEvent *)e; |
2747 | + emit(valueChanged(ce->value())); |
2748 | + } else { |
2749 | + return QObject::eventFilter(o,e); |
2750 | + } |
2751 | + return true; |
2752 | +} |
2753 | + |
2754 | +void ControlObjectThreadMain::slotValueChanged(double, QObject* pSetter) { |
2755 | + // The value argument to this function is in value space, but for some of |
2756 | + // our subclasses (e.g. ControlObjectThreadWidget) emit valueChanged(double) |
2757 | + // should emit in parameter space. So we emit the value of get() instead |
2758 | + // which will get the correct value. |
2759 | + |
2760 | + // If we are already running in the main thread, then go ahead and update. |
2761 | + if (QThread::currentThread() == QApplication::instance()->thread()) { |
2762 | + if (pSetter != this) { |
2763 | + emit(valueChanged(get())); |
2764 | + } else { |
2765 | + emit(valueChangedByThis(get())); |
2766 | + } |
2767 | + } else { |
2768 | + // Otherwise, we have to post the event to the main thread event queue |
2769 | + // and then catch the event via eventFilter. |
2770 | + QApplication::postEvent(this, new ControlEvent(get())); |
2771 | + } |
2772 | + |
2773 | +} |
2774 | |
2775 | === modified file 'mixxx/src/controlobjectthreadmain.h' |
2776 | --- mixxx/src/controlobjectthreadmain.h 2013-03-14 00:13:02 +0000 |
2777 | +++ mixxx/src/controlobjectthreadmain.h 2013-05-16 01:44:29 +0000 |
2778 | @@ -12,7 +12,7 @@ |
2779 | // ControlObjectThreadMain is a variant of ControlObjectThread that should only |
2780 | // ever have its methods called by the main thread. The benefit is that the |
2781 | // valueChanged() signal is proxied to the main thread automatically and the |
2782 | -// get()/set()/add()/sub() methods are lock-free and performant relative to |
2783 | +// get()/set() methods are lock-free and performant relative to |
2784 | // ControlObjectThread since COT requires using a mutex to maintain the |
2785 | // integrity of the control value. If you create a COTM, you must make sure to |
2786 | // only call its methods from the main thread. |
2787 | @@ -20,6 +20,14 @@ |
2788 | Q_OBJECT |
2789 | public: |
2790 | ControlObjectThreadMain(ControlObject *pControlObject, QObject* pParent=NULL); |
2791 | + |
2792 | + bool eventFilter(QObject* o, QEvent* e); |
2793 | + |
2794 | + protected slots: |
2795 | + // Receives the value from the master control, proxies it to the main |
2796 | + // thread, and re-emits either valueChanged(double) or |
2797 | + // valueChangedByThis(double) based on pSetter. |
2798 | + virtual void slotValueChanged(double v, QObject* pSetter); |
2799 | }; |
2800 | |
2801 | #endif |
2802 | |
2803 | === modified file 'mixxx/src/controlobjectthreadwidget.cpp' |
2804 | --- mixxx/src/controlobjectthreadwidget.cpp 2013-03-14 18:33:05 +0000 |
2805 | +++ mixxx/src/controlobjectthreadwidget.cpp 2013-05-16 01:44:29 +0000 |
2806 | @@ -6,12 +6,6 @@ |
2807 | |
2808 | ControlObjectThreadWidget::ControlObjectThreadWidget(ControlObject * pControlObject, QObject* pParent) |
2809 | : ControlObjectThreadMain(pControlObject, pParent) { |
2810 | - // ControlObjectThread's constructor sets m_dValue to |
2811 | - // m_pControlObject->get(). Since we represent the widget's value, we need |
2812 | - // to reset m_dValue to be the result of getValueToWidget. |
2813 | - if (m_pControlObject != NULL) { |
2814 | - slotParentValueChanged(get()); |
2815 | - } |
2816 | } |
2817 | |
2818 | ControlObjectThreadWidget::~ControlObjectThreadWidget() { |
2819 | @@ -22,7 +16,7 @@ |
2820 | EmitOption emitOption, Qt::MouseButton state) { |
2821 | if (connectValueFromWidget) { |
2822 | connect(widget, SIGNAL(valueReset()), |
2823 | - this, SLOT(slotReset())); |
2824 | + this, SLOT(reset())); |
2825 | |
2826 | if (emitOption & EMIT_ON_PRESS) { |
2827 | switch (state) { |
2828 | @@ -77,37 +71,12 @@ |
2829 | emit(valueChanged(get())); |
2830 | } |
2831 | |
2832 | -void ControlObjectThreadWidget::slotReset() { |
2833 | - if (m_pControlObject) { |
2834 | - m_pControlObject->reset(); |
2835 | - |
2836 | - } |
2837 | -} |
2838 | - |
2839 | double ControlObjectThreadWidget::get() { |
2840 | - if (m_pControlObject) { |
2841 | - return m_pControlObject->getValueToWidget(m_pControlObject->get()); |
2842 | - } else { |
2843 | - return 0.0; |
2844 | - } |
2845 | -} |
2846 | - |
2847 | -void ControlObjectThreadWidget::slotSet(double v) { |
2848 | - m_pControlObject->set(m_pControlObject->getValueFromWidget(v)); |
2849 | -} |
2850 | - |
2851 | -void ControlObjectThreadWidget::add(double v) { |
2852 | - m_pControlObject->add(m_pControlObject->getValueFromWidget(v)); |
2853 | -} |
2854 | - |
2855 | -void ControlObjectThreadWidget::sub(double v) { |
2856 | - m_pControlObject->sub(m_pControlObject->getValueFromWidget(v)); |
2857 | -} |
2858 | - |
2859 | -// Receives the Value from the parent and may scales the vale and re-emit it again |
2860 | -void ControlObjectThreadWidget::slotParentValueChanged(double v) { |
2861 | - if (m_pControlObject) { |
2862 | - double widgetValue = m_pControlObject->getValueToWidget(v); |
2863 | - emit(valueChanged(widgetValue)); |
2864 | + return m_pControl ? m_pControl->getWidgetParameter() : 0.0; |
2865 | +} |
2866 | + |
2867 | +void ControlObjectThreadWidget::set(double v) { |
2868 | + if (m_pControl) { |
2869 | + m_pControl->setWidgetParameter(v, this); |
2870 | } |
2871 | } |
2872 | |
2873 | === modified file 'mixxx/src/controlobjectthreadwidget.h' |
2874 | --- mixxx/src/controlobjectthreadwidget.h 2013-03-14 14:57:52 +0000 |
2875 | +++ mixxx/src/controlobjectthreadwidget.h 2013-05-16 01:44:29 +0000 |
2876 | @@ -22,10 +22,9 @@ |
2877 | @author Tue Haste Andersen |
2878 | */ |
2879 | |
2880 | -class ControlObjectThreadWidget : public ControlObjectThreadMain |
2881 | -{ |
2882 | +class ControlObjectThreadWidget : public ControlObjectThreadMain { |
2883 | Q_OBJECT |
2884 | -public: |
2885 | + public: |
2886 | |
2887 | enum EmitOption { |
2888 | EMIT_NEVER = 0x00, |
2889 | @@ -45,15 +44,8 @@ |
2890 | |
2891 | virtual double get(); |
2892 | |
2893 | - virtual void add(double v); |
2894 | - |
2895 | - virtual void sub(double v); |
2896 | - |
2897 | - private slots: |
2898 | - void slotReset(); |
2899 | - // Receives the Value from the parent and may scales the vale and re-emit it again |
2900 | - virtual void slotSet(double v); |
2901 | - virtual void slotParentValueChanged(double v); |
2902 | + public slots: |
2903 | + virtual void set(double v); |
2904 | }; |
2905 | |
2906 | #endif |
2907 | |
2908 | === modified file 'mixxx/src/controlpotmeter.cpp' |
2909 | --- mixxx/src/controlpotmeter.cpp 2013-03-17 16:08:55 +0000 |
2910 | +++ mixxx/src/controlpotmeter.cpp 2013-05-16 01:44:29 +0000 |
2911 | @@ -100,13 +100,11 @@ |
2912 | { |
2913 | } |
2914 | |
2915 | -double ControlPotmeter::getMin() |
2916 | -{ |
2917 | +double ControlPotmeter::getMin() const { |
2918 | return m_dMinValue; |
2919 | } |
2920 | |
2921 | -double ControlPotmeter::getMax() |
2922 | -{ |
2923 | +double ControlPotmeter::getMax() const { |
2924 | return m_dMaxValue; |
2925 | } |
2926 | |
2927 | @@ -125,47 +123,19 @@ |
2928 | m_dMinValue = dMinValue; |
2929 | m_dMaxValue = dMaxValue; |
2930 | m_dValueRange = m_dMaxValue - m_dMinValue; |
2931 | - m_dDefaultValue = m_dMinValue + 0.5 * m_dValueRange; |
2932 | - set(m_dDefaultValue); |
2933 | + double default_value = m_dMinValue + 0.5 * m_dValueRange; |
2934 | + |
2935 | + if (m_pControl) { |
2936 | + ControlNumericBehavior* pOldBehavior = m_pControl->setBehavior( |
2937 | + new ControlPotmeterBehavior(dMinValue, dMaxValue)); |
2938 | + delete pOldBehavior; |
2939 | + } |
2940 | + |
2941 | + setDefaultValue(default_value); |
2942 | + set(default_value); |
2943 | //qDebug() << "" << this << ", min " << m_dMinValue << ", max " << m_dMaxValue << ", range " << m_dValueRange << ", val " << m_dValue; |
2944 | } |
2945 | |
2946 | -double ControlPotmeter::getValueToWidget(double dValue) |
2947 | -{ |
2948 | - double out = (dValue-m_dMinValue)/m_dValueRange; |
2949 | - return (out < 0.5) ? out*128. : out*126. + 1.; |
2950 | -} |
2951 | - |
2952 | -double ControlPotmeter::GetMidiValue() |
2953 | -{ |
2954 | - double out = (get()-m_dMinValue)/m_dValueRange; |
2955 | - return (out < 0.5) ? out*128. : out*126. + 1.; |
2956 | -} |
2957 | - |
2958 | -double ControlPotmeter::getValueFromWidget(double dValue) |
2959 | -{ |
2960 | - double out = (dValue < 64) ? dValue / 128. : (dValue-1) / 126.; |
2961 | - return m_dMinValue + out * m_dValueRange; |
2962 | -} |
2963 | - |
2964 | -void ControlPotmeter::setValueFromThread(double dValue) |
2965 | -{ |
2966 | - if (dValue > m_dMaxValue) { |
2967 | - set(m_dMaxValue); |
2968 | - } else if (dValue < m_dMinValue) { |
2969 | - set(m_dMinValue); |
2970 | - } else { |
2971 | - set(dValue); |
2972 | - } |
2973 | -} |
2974 | - |
2975 | -void ControlPotmeter::setValueFromMidi(MidiOpCode o, double v) |
2976 | -{ |
2977 | - Q_UNUSED(o); |
2978 | - double out = (v < 64) ? v / 128. : (v-1) / 126.; |
2979 | - set(m_dMinValue + out * m_dValueRange); |
2980 | -} |
2981 | - |
2982 | void ControlPotmeter::incValue(double keypos) |
2983 | { |
2984 | if (keypos>0) |
2985 | @@ -245,7 +215,7 @@ |
2986 | |
2987 | void ControlPotmeter::setToDefault(double v) { |
2988 | if (v > 0) { |
2989 | - set(m_dDefaultValue); |
2990 | + reset(); |
2991 | } |
2992 | } |
2993 | |
2994 | |
2995 | === modified file 'mixxx/src/controlpotmeter.h' |
2996 | --- mixxx/src/controlpotmeter.h 2013-03-17 16:08:55 +0000 |
2997 | +++ mixxx/src/controlpotmeter.h 2013-05-16 01:44:29 +0000 |
2998 | @@ -35,22 +35,15 @@ |
2999 | ControlPotmeter(ConfigKey key, double dMinValue=0.0, double dMaxValue=1.0); |
3000 | ~ControlPotmeter(); |
3001 | /** Returns the minimum allowed value */ |
3002 | - double getMin(); |
3003 | + double getMin() const; |
3004 | /** Returns the maximum allowed value */ |
3005 | - double getMax(); |
3006 | + double getMax() const; |
3007 | /** Sets the step size of the associated PushButtons */ |
3008 | void setStep(double); |
3009 | /** Sets the small step size of the associated PushButtons */ |
3010 | void setSmallStep(double); |
3011 | - /** Sets the minimum and maximum allowed value. The control value is reset when calling |
3012 | - * this method */ |
3013 | - void setRange(double dMinValue, double dMaxValue); |
3014 | - double getValueFromWidget(double dValue); |
3015 | - double getValueToWidget(double dValue); |
3016 | - double GetMidiValue(); |
3017 | |
3018 | public slots: |
3019 | - void setValueFromThread(double dValue); |
3020 | /** Increases the value. This method is called from an associated PushButton control */ |
3021 | void incValue(double); |
3022 | /** Decreases the value. This method is called from an associated PushButton control */ |
3023 | @@ -73,7 +66,9 @@ |
3024 | void toggleMinusValue(double); |
3025 | |
3026 | protected: |
3027 | - void setValueFromMidi(MidiOpCode o, double v); |
3028 | + /** Sets the minimum and maximum allowed value. The control value is reset when calling |
3029 | + * this method */ |
3030 | + void setRange(double dMinValue, double dMaxValue); |
3031 | |
3032 | double m_dMaxValue; |
3033 | double m_dMinValue; |
3034 | |
3035 | === modified file 'mixxx/src/controlpushbutton.cpp' |
3036 | --- mixxx/src/controlpushbutton.cpp 2013-03-13 16:31:06 +0000 |
3037 | +++ mixxx/src/controlpushbutton.cpp 2013-05-16 01:44:29 +0000 |
3038 | @@ -17,9 +17,6 @@ |
3039 | |
3040 | #include "controlpushbutton.h" |
3041 | |
3042 | -// static |
3043 | -const int ControlPushButton::kPowerWindowTimeMillis = 300; |
3044 | - |
3045 | /* -------- ------------------------------------------------------ |
3046 | Purpose: Creates a new simulated latching push-button. |
3047 | Input: key - Key for the configuration file |
3048 | @@ -28,6 +25,13 @@ |
3049 | ControlObject(key, false), |
3050 | m_buttonMode(PUSH), |
3051 | m_iNoStates(2) { |
3052 | + if (m_pControl) { |
3053 | + ControlNumericBehavior* pOldBehavior = m_pControl->setBehavior( |
3054 | + new ControlPushButtonBehavior( |
3055 | + static_cast<ControlPushButtonBehavior::ButtonMode>(m_buttonMode), |
3056 | + m_iNoStates)); |
3057 | + delete pOldBehavior; |
3058 | + } |
3059 | } |
3060 | |
3061 | ControlPushButton::~ControlPushButton() { |
3062 | @@ -37,62 +41,25 @@ |
3063 | void ControlPushButton::setButtonMode(enum ButtonMode mode) { |
3064 | //qDebug() << "Setting " << m_Key.group << m_Key.item << "as toggle"; |
3065 | m_buttonMode = mode; |
3066 | + |
3067 | + if (m_pControl) { |
3068 | + ControlNumericBehavior* pOldBehavior = m_pControl->setBehavior( |
3069 | + new ControlPushButtonBehavior( |
3070 | + static_cast<ControlPushButtonBehavior::ButtonMode>(m_buttonMode), |
3071 | + m_iNoStates)); |
3072 | + delete pOldBehavior; |
3073 | + } |
3074 | } |
3075 | |
3076 | void ControlPushButton::setStates(int num_states) { |
3077 | m_iNoStates = num_states; |
3078 | -} |
3079 | - |
3080 | -void ControlPushButton::setValueFromMidi(MidiOpCode o, double v) { |
3081 | - // keyboard events are handled by this function as well |
3082 | - //if (m_bMidiSimulateLatching) |
3083 | - |
3084 | - //qDebug() << "bMidiSimulateLatching is true!"; |
3085 | - // Only react on NOTE_ON midi events if simulating latching... |
3086 | - |
3087 | - //qDebug() << o << v; |
3088 | - |
3089 | - // This block makes push-buttons act as power window buttons. |
3090 | - if (m_buttonMode == POWERWINDOW && m_iNoStates == 2) { |
3091 | - if (o == MIDI_NOTE_ON) { |
3092 | - if (v > 0.) { |
3093 | - double value = get(); |
3094 | - set(!value); |
3095 | - m_pushTimer.setSingleShot(true); |
3096 | - m_pushTimer.start(kPowerWindowTimeMillis); |
3097 | - } |
3098 | - } else if (o == MIDI_NOTE_OFF) { |
3099 | - if (!m_pushTimer.isActive()) { |
3100 | - set(0.0); |
3101 | - } |
3102 | - } |
3103 | - } else if (m_buttonMode == TOGGLE) { |
3104 | - // This block makes push-buttons act as toggle buttons. |
3105 | - if (m_iNoStates > 2) { //multistate button |
3106 | - if (v > 0.) { //looking for NOTE_ON doesn't seem to work... |
3107 | - double value = get(); |
3108 | - value++; |
3109 | - if (value >= m_iNoStates) { |
3110 | - set(0); |
3111 | - } else { |
3112 | - set(value); |
3113 | - } |
3114 | - } |
3115 | - } else { |
3116 | - if (o == MIDI_NOTE_ON) { |
3117 | - if (v > 0.) { |
3118 | - double value = get(); |
3119 | - set(!value); |
3120 | - } |
3121 | - } |
3122 | - } |
3123 | - } else { //Not a toggle button (trigger only when button pushed) |
3124 | - if (o == MIDI_NOTE_ON) { |
3125 | - double value = get(); |
3126 | - set(!value); |
3127 | - } else if (o == MIDI_NOTE_OFF) { |
3128 | - set(0.0); |
3129 | - } |
3130 | + |
3131 | + if (m_pControl) { |
3132 | + ControlNumericBehavior* pOldBehavior = m_pControl->setBehavior( |
3133 | + new ControlPushButtonBehavior( |
3134 | + static_cast<ControlPushButtonBehavior::ButtonMode>(m_buttonMode), |
3135 | + m_iNoStates)); |
3136 | + delete pOldBehavior; |
3137 | } |
3138 | } |
3139 | |
3140 | |
3141 | === modified file 'mixxx/src/controlpushbutton.h' |
3142 | --- mixxx/src/controlpushbutton.h 2012-05-01 05:59:37 +0000 |
3143 | +++ mixxx/src/controlpushbutton.h 2013-05-16 01:44:29 +0000 |
3144 | @@ -21,7 +21,6 @@ |
3145 | #include "controlobject.h" |
3146 | #include "controllers/midi/midimessage.h" |
3147 | #include "defs.h" |
3148 | -#include <QTimer> |
3149 | |
3150 | /** |
3151 | *@author Tue and Ken Haste Andersen |
3152 | @@ -31,11 +30,10 @@ |
3153 | Q_OBJECT |
3154 | public: |
3155 | enum ButtonMode { |
3156 | - PUSH, |
3157 | + PUSH = 0, |
3158 | TOGGLE, |
3159 | POWERWINDOW |
3160 | }; |
3161 | - static const int kPowerWindowTimeMillis; |
3162 | |
3163 | ControlPushButton(ConfigKey key); |
3164 | virtual ~ControlPushButton(); |
3165 | @@ -46,13 +44,9 @@ |
3166 | void setButtonMode(enum ButtonMode mode); |
3167 | void setStates(int num_states); |
3168 | |
3169 | - protected: |
3170 | - void setValueFromMidi(MidiOpCode o, double v); |
3171 | - |
3172 | private: |
3173 | enum ButtonMode m_buttonMode; |
3174 | int m_iNoStates; |
3175 | - QTimer m_pushTimer; |
3176 | }; |
3177 | |
3178 | #endif |
3179 | |
3180 | === modified file 'mixxx/src/controlttrotary.cpp' |
3181 | --- mixxx/src/controlttrotary.cpp 2013-03-13 16:31:06 +0000 |
3182 | +++ mixxx/src/controlttrotary.cpp 2013-05-16 01:44:29 +0000 |
3183 | @@ -20,30 +20,13 @@ |
3184 | Purpose: Creates a new rotary encoder |
3185 | Input: key |
3186 | -------- ------------------------------------------------------ */ |
3187 | -ControlTTRotary::ControlTTRotary(ConfigKey key) : ControlObject(key) |
3188 | -{ |
3189 | -} |
3190 | - |
3191 | -double ControlTTRotary::getValueFromWidget(double dValue) |
3192 | -{ |
3193 | - // Non-linear scaling |
3194 | - double temp = (((dValue-64.)*(dValue-64.))/64.); |
3195 | - if ((dValue-64.)<0) |
3196 | - temp = -temp; |
3197 | - |
3198 | - //qDebug() << "tt rotary in " << dValue << ", out " << temp; |
3199 | - |
3200 | - return temp; //dValue-64.; |
3201 | -} |
3202 | - |
3203 | -double ControlTTRotary::getValueToWidget(double dValue) |
3204 | -{ |
3205 | - return dValue*200.+64.; |
3206 | -} |
3207 | - |
3208 | -void ControlTTRotary::setValueFromMidi(MidiOpCode o, double v) |
3209 | -{ |
3210 | - Q_UNUSED(o); |
3211 | - set(v); |
3212 | -} |
3213 | +ControlTTRotary::ControlTTRotary(ConfigKey key) : ControlObject(key) { |
3214 | + if (m_pControl) { |
3215 | + ControlNumericBehavior* pOldBehavior = m_pControl->setBehavior( |
3216 | + new ControlTTRotaryBehavior()); |
3217 | + delete pOldBehavior; |
3218 | + } |
3219 | +} |
3220 | + |
3221 | + |
3222 | |
3223 | |
3224 | === modified file 'mixxx/src/controlttrotary.h' |
3225 | --- mixxx/src/controlttrotary.h 2012-03-17 17:42:44 +0000 |
3226 | +++ mixxx/src/controlttrotary.h 2013-05-16 01:44:29 +0000 |
3227 | @@ -20,20 +20,10 @@ |
3228 | #include "configobject.h" |
3229 | #include "controlobject.h" |
3230 | |
3231 | -/** Turn Table rotary controller class. The turntable rotary sends midi events: 0 when turning |
3232 | - * backwards, and 1 when turning forward. This class keeps track of it's speed, using a timer |
3233 | - * interrupt */ |
3234 | -class ControlTTRotary : public ControlObject |
3235 | -{ |
3236 | +class ControlTTRotary : public ControlObject { |
3237 | Q_OBJECT |
3238 | -public: |
3239 | + public: |
3240 | ControlTTRotary(ConfigKey key); |
3241 | - |
3242 | - double getValueFromWidget(double dValue); |
3243 | - double getValueToWidget(double dValue); |
3244 | - |
3245 | -protected: |
3246 | - void setValueFromMidi(MidiOpCode o, double v); |
3247 | }; |
3248 | |
3249 | #endif |
3250 | |
3251 | === modified file 'mixxx/src/dlgabout.cpp' |
3252 | --- mixxx/src/dlgabout.cpp 2011-12-22 18:55:10 +0000 |
3253 | +++ mixxx/src/dlgabout.cpp 2013-05-16 01:44:29 +0000 |
3254 | @@ -17,15 +17,202 @@ |
3255 | |
3256 | #include "dlgabout.h" |
3257 | |
3258 | -#include <qlineedit.h> |
3259 | -#include <qwidget.h> |
3260 | -#include <qslider.h> |
3261 | -#include <qlabel.h> |
3262 | -#include <qstring.h> |
3263 | -#include <qpushbutton.h> |
3264 | +#include "defs_version.h" |
3265 | |
3266 | DlgAbout::DlgAbout(QWidget* parent) : QDialog(parent), Ui::DlgAboutDlg() { |
3267 | setupUi(this); |
3268 | + |
3269 | + QString buildBranch, buildRevision; |
3270 | +#ifdef BUILD_BRANCH |
3271 | + buildBranch = BUILD_BRANCH; |
3272 | +#endif |
3273 | +#ifdef BUILD_REV |
3274 | + buildRevision = BUILD_REV; |
3275 | +#endif |
3276 | + |
3277 | + QStringList version; |
3278 | + version.append(VERSION); |
3279 | + if (!buildBranch.isEmpty() || !buildRevision.isEmpty()) { |
3280 | + QStringList buildInfo; |
3281 | + buildInfo.append("build"); |
3282 | + if (!buildBranch.isEmpty()) { |
3283 | + buildInfo.append(buildBranch); |
3284 | + } |
3285 | + if (!buildRevision.isEmpty()) { |
3286 | + buildInfo.append(QString("r%1").arg(buildRevision)); |
3287 | + } |
3288 | + version.append(QString("(%1)").arg(buildInfo.join(" "))); |
3289 | + } |
3290 | + version_label->setText(version.join(" ")); |
3291 | + |
3292 | + QString s_devTeam = QString(tr("Mixxx %1 Development Team")).arg(VERSION); |
3293 | + QString s_contributions = tr("With contributions from:"); |
3294 | + QString s_specialThanks = tr("And special thanks to:"); |
3295 | + QString s_pastDevs = tr("Past Developers"); |
3296 | + QString s_pastContribs = tr("Past Contributors"); |
3297 | + |
3298 | + QString credits = QString("<p align=\"center\"><b>%1</b></p>" |
3299 | +"<p align=\"center\">" |
3300 | +"Albert Santoni<br>" |
3301 | +"RJ Ryan<br>" |
3302 | +"Sean Pappalardo<br>" |
3303 | +"Phillip Whelan<br>" |
3304 | +"Tobias Rafreider<br>" |
3305 | +"S. Brandt<br>" |
3306 | +"Bill Good<br>" |
3307 | +"Owen Williams<br>" |
3308 | +"Vittorio Colao<br>" |
3309 | +"Daniel Schürmann<br>" |
3310 | +"Thomas Vincent<br>" |
3311 | +"Ilkka Tuohela<br>" |
3312 | +"Max Linke<br>" |
3313 | + |
3314 | +"</p>" |
3315 | +"<p align=\"center\"><b>%2</b></p>" |
3316 | +"<p align=\"center\">" |
3317 | +"Mark Hills<br>" |
3318 | +"Andre Roth<br>" |
3319 | +"Robin Sheat<br>" |
3320 | +"Mark Glines<br>" |
3321 | +"Mathieu Rene<br>" |
3322 | +"Miko Kiiski<br>" |
3323 | +"Brian Jackson<br>" |
3324 | +"Andreas Pflug<br>" |
3325 | +"Bas van Schaik<br>" |
3326 | +"Ján Jockusch<br>" |
3327 | +"Oliver Stöneberg<br>" |
3328 | +"Jan Jockusch<br>" |
3329 | +"C. Stewart<br>" |
3330 | +"Bill Egert<br>" |
3331 | +"Zach Shutters<br>" |
3332 | +"Owen Bullock<br>" |
3333 | +"Graeme Mathieson<br>" |
3334 | +"Sebastian Actist<br>" |
3335 | +"Jussi Sainio<br>" |
3336 | +"David Gnedt<br>" |
3337 | +"Antonio Passamani<br>" |
3338 | +"Guy Martin<br>" |
3339 | +"Anders Gunnarsson<br>" |
3340 | +"Alex Barker<br>" |
3341 | +"Mikko Jania<br>" |
3342 | +"Juan Pedro Bolívar Puente<br>" |
3343 | +"Linus Amvall<br>" |
3344 | +"Irwin Céspedes B<br>" |
3345 | +"Micz Flor<br>" |
3346 | +"Daniel James<br>" |
3347 | +"Mika Haulo<br>" |
3348 | +"Matthew Mikolay<br>" |
3349 | +"Tom Mast<br>" |
3350 | +"Miko Kiiski<br>" |
3351 | +"Vinícius Dias dos Santos<br>" |
3352 | +"Joe Colosimo<br>" |
3353 | +"Shashank Kumar<br>" |
3354 | +"Till Hofmann<br>" |
3355 | +"Peter Vágner<br>" |
3356 | +"Thanasis Liappis<br>" |
3357 | +"Jens Nachtigall<br>" |
3358 | +"Scott Ullrich<br>" |
3359 | +"Jonas Ådahl<br>" |
3360 | +"Jonathan Costers<br>" |
3361 | +"Daniel Lindenfelser<br>" |
3362 | +"Maxime Bochon<br>" |
3363 | +"Akash Shetye<br>" |
3364 | +"Pascal Bleser<br>" |
3365 | +"Florian Mahlknecht<br>" |
3366 | +"Ben Clark<br>" |
3367 | +"Tom Gascoigne<br>" |
3368 | +"Neale Pickett<br>" |
3369 | +"Aaron Mavrinac<br>" |
3370 | +"Markus Härer<br>" |
3371 | +"Andrey Smelov<br>" |
3372 | +"Scott Stewart<br>" |
3373 | +"Nimatek<br>" |
3374 | +"Alban Bedel<br>" |
3375 | +"Stefan Nürnberger<br>" |
3376 | +"Steven Boswell<br>" |
3377 | +"João Reys Santos<br>" |
3378 | +"Carl Pillot<br>" |
3379 | +"Vedant Agarwala<br>" |
3380 | + |
3381 | +"</p>" |
3382 | +"<p align=\"center\"><b>%3</b></p>" |
3383 | +"<p align=\"center\">" |
3384 | +"Vestax<br>" |
3385 | +"Stanton<br>" |
3386 | +"Hercules<br>" |
3387 | +"EKS<br>" |
3388 | +"Echo Digital Audio<br>" |
3389 | +"JP Disco<br>" |
3390 | +"Google Summer of Code<br>" |
3391 | +"Adam Bellinson<br>" |
3392 | +"Alexandre Bancel<br>" |
3393 | +"Melanie Thielker<br>" |
3394 | +"Julien Rosener<br>" |
3395 | +"Pau Arumí<br>" |
3396 | +"David Garcia<br>" |
3397 | +"Seb Ruiz<br>" |
3398 | +"Joseph Mattiello<br>" |
3399 | +"</p>" |
3400 | + |
3401 | +"<p align=\"center\"><b>%4</b></p>" |
3402 | +"<p align=\"center\">" |
3403 | +"Tue Haste Andersen<br>" |
3404 | +"Ken Haste Andersen<br>" |
3405 | +"Cedric Gestes<br>" |
3406 | +"John Sully<br>" |
3407 | +"Torben Hohn<br>" |
3408 | +"Peter Chang<br>" |
3409 | +"Micah Lee<br>" |
3410 | +"Ben Wheeler<br>" |
3411 | +"Wesley Stessens<br>" |
3412 | +"Nathan Prado<br>" |
3413 | +"Zach Elko<br>" |
3414 | +"Tom Care<br>" |
3415 | +"Pawel Bartkiewicz<br>" |
3416 | +"Nick Guenther<br>" |
3417 | +"Adam Davison<br>" |
3418 | +"Garth Dahlstrom<br>" |
3419 | +"</p>" |
3420 | + |
3421 | +"<p align=\"center\"><b>%5</b></p>" |
3422 | +"<p align=\"center\">" |
3423 | +"Ludek Horácek<br>" |
3424 | +"Svein Magne Bang<br>" |
3425 | +"Kristoffer Jensen<br>" |
3426 | +"Ingo Kossyk<br>" |
3427 | +"Mads Holm<br>" |
3428 | +"Lukas Zapletal<br>" |
3429 | +"Jeremie Zimmermann<br>" |
3430 | +"Gianluca Romanin<br>" |
3431 | +"Tim Jackson<br>" |
3432 | +"Stefan Langhammer<br>" |
3433 | +"Frank Willascheck<br>" |
3434 | +"Jeff Nelson<br>" |
3435 | +"Kevin Schaper<br>" |
3436 | +"Alex Markley<br>" |
3437 | +"Oriol Puigbó<br>" |
3438 | +"Ulrich Heske<br>" |
3439 | +"James Hagerman<br>" |
3440 | +"quil0m80<br>" |
3441 | +"Martin Sakmár<br>" |
3442 | +"Ilian Persson<br>" |
3443 | +"Dave Jarvis<br>" |
3444 | +"Thomas Baag<br>" |
3445 | +"Karlis Kalnins<br>" |
3446 | +"Amias Channer<br>" |
3447 | +"Sacha Berger<br>" |
3448 | +"James Evans<br>" |
3449 | +"Martin Sakmar<br>" |
3450 | +"Navaho Gunleg<br>" |
3451 | +"Gavin Pryke<br>" |
3452 | +"Michael Pujos<br>" |
3453 | +"Claudio Bantaloukas<br>" |
3454 | +"Pavol Rusnak<br>" |
3455 | +"Bruno Buccolo<br>" |
3456 | +"Ryan Baker<br>" |
3457 | + "</p>").arg(s_devTeam,s_contributions,s_specialThanks,s_pastDevs,s_pastContribs); |
3458 | + |
3459 | + textBrowser->setHtml(credits); |
3460 | } |
3461 | |
3462 | DlgAbout::~DlgAbout() { |
3463 | |
3464 | === removed file 'mixxx/src/dlgbpmscheme.cpp' |
3465 | --- mixxx/src/dlgbpmscheme.cpp 2010-01-14 23:32:38 +0000 |
3466 | +++ mixxx/src/dlgbpmscheme.cpp 1970-01-01 00:00:00 +0000 |
3467 | @@ -1,58 +0,0 @@ |
3468 | -/*************************************************************************** |
3469 | - dlgbpmscheme.cpp - description |
3470 | - ------------------- |
3471 | - begin : Thu Jun 7 2007 |
3472 | - copyright : (C) 2007 by John Sully |
3473 | - email : jsully@scs.ryerson.ca |
3474 | -***************************************************************************/ |
3475 | - |
3476 | -/*************************************************************************** |
3477 | -* * |
3478 | -* This program is free software; you can redistribute it and/or modify * |
3479 | -* it under the terms of the GNU General Public License as published by * |
3480 | -* the Free Software Foundation; either version 2 of the License, or * |
3481 | -* (at your option) any later version. * |
3482 | -* * |
3483 | -***************************************************************************/ |
3484 | - |
3485 | -#include <QtCore> |
3486 | - |
3487 | -#include "dlgbpmscheme.h" |
3488 | -#include "bpm/bpmscheme.h" |
3489 | - |
3490 | -DlgBpmScheme::DlgBpmScheme(BpmScheme *& bpmScheme) : QDialog(), Ui::DlgBpmSchemeDlg(), m_BpmScheme(bpmScheme) |
3491 | -{ |
3492 | - setupUi(this); |
3493 | - |
3494 | - connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotApply())); |
3495 | - //connect(chkAnalyzeEntireSong, SIGNAL(stateChanged(int)), this, SLOT(slotSetAnalyzeMode(int))); |
3496 | - |
3497 | - // Check to see if this is a new scheme. If so, create it with default values |
3498 | - if(!bpmScheme) |
3499 | - { |
3500 | - bpmScheme = new BpmScheme("New Scheme Name", 50, 150, false); |
3501 | - } |
3502 | - |
3503 | - // Populate the dialog values |
3504 | - txtSchemeName->setText(bpmScheme->getName()); |
3505 | - spinBpmMin->setValue(bpmScheme->getMinBpm()); |
3506 | - spinBpmMax->setValue(bpmScheme->getMaxBpm()); |
3507 | - chkAnalyzeEntireSong->setChecked(bpmScheme->getAnalyzeEntireSong()); |
3508 | -} |
3509 | - |
3510 | -DlgBpmScheme::~DlgBpmScheme() |
3511 | -{ |
3512 | -} |
3513 | - |
3514 | -void DlgBpmScheme::slotApply() |
3515 | -{ |
3516 | - m_BpmScheme->setName(txtSchemeName->text()); |
3517 | - m_BpmScheme->setMinBpm(spinBpmMin->value()); |
3518 | - m_BpmScheme->setMaxBpm(spinBpmMax->value()); |
3519 | - m_BpmScheme->setAnalyzeEntireSong(chkAnalyzeEntireSong->isChecked()); |
3520 | -} |
3521 | - |
3522 | -void DlgBpmScheme::slotUpdate() |
3523 | -{ |
3524 | -} |
3525 | - |
3526 | |
3527 | === removed file 'mixxx/src/dlgbpmscheme.h' |
3528 | --- mixxx/src/dlgbpmscheme.h 2008-01-30 13:37:36 +0000 |
3529 | +++ mixxx/src/dlgbpmscheme.h 1970-01-01 00:00:00 +0000 |
3530 | @@ -1,38 +0,0 @@ |
3531 | - |
3532 | - |
3533 | -/*************************************************************************** |
3534 | - * * |
3535 | - * This program is free software; you can redistribute it and/or modify * |
3536 | - * it under the terms of the GNU General Public License as published by * |
3537 | - * the Free Software Foundation; either version 2 of the License, or * |
3538 | - * (at your option) any later version. * |
3539 | - * * |
3540 | - ***************************************************************************/ |
3541 | - |
3542 | -#ifndef DLGBPMSCHEME_H |
3543 | -#define DLGBPMSCHEME_H |
3544 | - |
3545 | -#include "ui_dlgbpmschemedlg.h" |
3546 | -#include "configobject.h" |
3547 | -#include <qstring.h> |
3548 | - |
3549 | -class BpmScheme; |
3550 | - |
3551 | -class QWidget; |
3552 | - |
3553 | -class DlgBpmScheme : public QDialog, Ui::DlgBpmSchemeDlg { |
3554 | - Q_OBJECT |
3555 | -public: |
3556 | - DlgBpmScheme(BpmScheme *& bpmScheme); |
3557 | - ~DlgBpmScheme(); |
3558 | -public slots: |
3559 | - /** Apply changes to widget */ |
3560 | - void slotApply(); |
3561 | - void slotUpdate(); |
3562 | -signals: |
3563 | - void apply(const QString &); |
3564 | -private: |
3565 | - BpmScheme *& m_BpmScheme; |
3566 | -}; |
3567 | - |
3568 | -#endif |
3569 | |
3570 | === removed file 'mixxx/src/dlgbpmschemedlg.ui' |
3571 | --- mixxx/src/dlgbpmschemedlg.ui 2012-04-30 18:38:29 +0000 |
3572 | +++ mixxx/src/dlgbpmschemedlg.ui 1970-01-01 00:00:00 +0000 |
3573 | @@ -1,184 +0,0 @@ |
3574 | -<?xml version="1.0" encoding="UTF-8"?> |
3575 | -<ui version="4.0"> |
3576 | - <class>DlgBpmSchemeDlg</class> |
3577 | - <widget class="QDialog" name="DlgBpmSchemeDlg"> |
3578 | - <property name="geometry"> |
3579 | - <rect> |
3580 | - <x>0</x> |
3581 | - <y>0</y> |
3582 | - <width>352</width> |
3583 | - <height>172</height> |
3584 | - </rect> |
3585 | - </property> |
3586 | - <property name="windowTitle"> |
3587 | - <string>BPM Scheme</string> |
3588 | - </property> |
3589 | - <widget class="QDialogButtonBox" name="buttonBox"> |
3590 | - <property name="geometry"> |
3591 | - <rect> |
3592 | - <x>0</x> |
3593 | - <y>130</y> |
3594 | - <width>341</width> |
3595 | - <height>32</height> |
3596 | - </rect> |
3597 | - </property> |
3598 | - <property name="orientation"> |
3599 | - <enum>Qt::Horizontal</enum> |
3600 | - </property> |
3601 | - <property name="standardButtons"> |
3602 | - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> |
3603 | - </property> |
3604 | - </widget> |
3605 | - <widget class="QLineEdit" name="txtSchemeName"> |
3606 | - <property name="geometry"> |
3607 | - <rect> |
3608 | - <x>110</x> |
3609 | - <y>10</y> |
3610 | - <width>231</width> |
3611 | - <height>23</height> |
3612 | - </rect> |
3613 | - </property> |
3614 | - </widget> |
3615 | - <widget class="QLabel" name="label"> |
3616 | - <property name="geometry"> |
3617 | - <rect> |
3618 | - <x>10</x> |
3619 | - <y>10</y> |
3620 | - <width>111</width> |
3621 | - <height>18</height> |
3622 | - </rect> |
3623 | - </property> |
3624 | - <property name="text"> |
3625 | - <string>Scheme Name:</string> |
3626 | - </property> |
3627 | - <property name="buddy"> |
3628 | - <cstring>txtSchemeName</cstring> |
3629 | - </property> |
3630 | - </widget> |
3631 | - <widget class="QGroupBox" name="groupBox"> |
3632 | - <property name="geometry"> |
3633 | - <rect> |
3634 | - <x>10</x> |
3635 | - <y>40</y> |
3636 | - <width>331</width> |
3637 | - <height>51</height> |
3638 | - </rect> |
3639 | - </property> |
3640 | - <property name="title"> |
3641 | - <string>BPM Range</string> |
3642 | - </property> |
3643 | - <widget class="QSpinBox" name="spinBpmMin"> |
3644 | - <property name="geometry"> |
3645 | - <rect> |
3646 | - <x>80</x> |
3647 | - <y>20</y> |
3648 | - <width>71</width> |
3649 | - <height>23</height> |
3650 | - </rect> |
3651 | - </property> |
3652 | - <property name="minimum"> |
3653 | - <number>1</number> |
3654 | - </property> |
3655 | - <property name="maximum"> |
3656 | - <number>220</number> |
3657 | - </property> |
3658 | - </widget> |
3659 | - <widget class="QSpinBox" name="spinBpmMax"> |
3660 | - <property name="geometry"> |
3661 | - <rect> |
3662 | - <x>210</x> |
3663 | - <y>20</y> |
3664 | - <width>71</width> |
3665 | - <height>23</height> |
3666 | - </rect> |
3667 | - </property> |
3668 | - <property name="minimum"> |
3669 | - <number>1</number> |
3670 | - </property> |
3671 | - <property name="maximum"> |
3672 | - <number>220</number> |
3673 | - </property> |
3674 | - </widget> |
3675 | - <widget class="QLabel" name="label_2"> |
3676 | - <property name="geometry"> |
3677 | - <rect> |
3678 | - <x>170</x> |
3679 | - <y>20</y> |
3680 | - <width>31</width> |
3681 | - <height>18</height> |
3682 | - </rect> |
3683 | - </property> |
3684 | - <property name="text"> |
3685 | - <string>Max</string> |
3686 | - </property> |
3687 | - <property name="buddy"> |
3688 | - <cstring>spinBpmMax</cstring> |
3689 | - </property> |
3690 | - </widget> |
3691 | - <widget class="QLabel" name="label_3"> |
3692 | - <property name="geometry"> |
3693 | - <rect> |
3694 | - <x>40</x> |
3695 | - <y>20</y> |
3696 | - <width>31</width> |
3697 | - <height>18</height> |
3698 | - </rect> |
3699 | - </property> |
3700 | - <property name="text"> |
3701 | - <string>Min</string> |
3702 | - </property> |
3703 | - <property name="buddy"> |
3704 | - <cstring>spinBpmMin</cstring> |
3705 | - </property> |
3706 | - </widget> |
3707 | - </widget> |
3708 | - <widget class="QCheckBox" name="chkAnalyzeEntireSong"> |
3709 | - <property name="geometry"> |
3710 | - <rect> |
3711 | - <x>90</x> |
3712 | - <y>100</y> |
3713 | - <width>201</width> |
3714 | - <height>22</height> |
3715 | - </rect> |
3716 | - </property> |
3717 | - <property name="text"> |
3718 | - <string>Analyze Entire Track</string> |
3719 | - </property> |
3720 | - </widget> |
3721 | - </widget> |
3722 | - <resources/> |
3723 | - <connections> |
3724 | - <connection> |
3725 | - <sender>buttonBox</sender> |
3726 | - <signal>accepted()</signal> |
3727 | - <receiver>DlgBpmSchemeDlg</receiver> |
3728 | - <slot>accept()</slot> |
3729 | - <hints> |
3730 | - <hint type="sourcelabel"> |
3731 | - <x>248</x> |
3732 | - <y>254</y> |
3733 | - </hint> |
3734 | - <hint type="destinationlabel"> |
3735 | - <x>157</x> |
3736 | - <y>274</y> |
3737 | - </hint> |
3738 | - </hints> |
3739 | - </connection> |
3740 | - <connection> |
3741 | - <sender>buttonBox</sender> |
3742 | - <signal>rejected()</signal> |
3743 | - <receiver>DlgBpmSchemeDlg</receiver> |
3744 | - <slot>reject()</slot> |
3745 | - <hints> |
3746 | - <hint type="sourcelabel"> |
3747 | - <x>316</x> |
3748 | - <y>260</y> |
3749 | - </hint> |
3750 | - <hint type="destinationlabel"> |
3751 | - <x>286</x> |
3752 | - <y>274</y> |
3753 | - </hint> |
3754 | - </hints> |
3755 | - </connection> |
3756 | - </connections> |
3757 | -</ui> |
3758 | |
3759 | === removed file 'mixxx/src/dlgprefbpm.cpp' |
3760 | --- mixxx/src/dlgprefbpm.cpp 2012-11-20 00:40:18 +0000 |
3761 | +++ mixxx/src/dlgprefbpm.cpp 1970-01-01 00:00:00 +0000 |
3762 | @@ -1,455 +0,0 @@ |
3763 | -/*************************************************************************** |
3764 | - dlgprefbpm.cpp - description |
3765 | - ------------------- |
3766 | - begin : Thu Jun 7 2007 |
3767 | - copyright : (C) 2007 by John Sully |
3768 | - email : jsully@scs.ryerson.ca |
3769 | -***************************************************************************/ |
3770 | - |
3771 | -/*************************************************************************** |
3772 | -* * |
3773 | -* This program is free software; you can redistribute it and/or modify * |
3774 | -* it under the terms of the GNU General Public License as published by * |
3775 | -* the Free Software Foundation; either version 2 of the License, or * |
3776 | -* (at your option) any later version. * |
3777 | -* * |
3778 | -***************************************************************************/ |
3779 | - |
3780 | -#include <qlineedit.h> |
3781 | -#include <qfiledialog.h> |
3782 | -#include <qwidget.h> |
3783 | -#include <qspinbox.h> |
3784 | -#include <qcheckbox.h> |
3785 | -#include <qlabel.h> |
3786 | -#include <qstring.h> |
3787 | -#include <qpushbutton.h> |
3788 | -#include <QtCore> |
3789 | -#include <QMessageBox> |
3790 | - |
3791 | -#include "dlgprefbpm.h" |
3792 | -#include "dlgbpmscheme.h" |
3793 | -#include "bpm/bpmscheme.h" |
3794 | -#include "xmlparse.h" |
3795 | -#include "mixxx.h" |
3796 | - |
3797 | -#define CONFIG_KEY "[BPM]" |
3798 | - |
3799 | -DlgPrefBpm::DlgPrefBpm(QWidget * parent, ConfigObject<ConfigValue> * _config) |
3800 | - : QWidget(parent) { |
3801 | - config = _config; |
3802 | - |
3803 | - setupUi(this); |
3804 | - |
3805 | - // Connection |
3806 | - connect(chkDetectOnImport, SIGNAL(stateChanged(int)), this, SLOT(slotSetBpmDetectOnImport(int))); |
3807 | - connect(chkWriteID3, SIGNAL(stateChanged(int)), this, SLOT(slotSetWriteID3Tag(int))); |
3808 | - connect(chkEnableBpmDetection, SIGNAL(stateChanged(int)), this, SLOT(slotSetBpmEnabled(int))); |
3809 | - connect(chkAboveRange, SIGNAL(stateChanged(int)), this, SLOT(slotSetAboveRange(int))); |
3810 | - |
3811 | - // TODO: Move this over the the scheme dialog |
3812 | - |
3813 | - connect(btnAdd, SIGNAL(pressed()), this, SLOT(slotAddBpmScheme())); |
3814 | - connect(btnEdit, SIGNAL(pressed()), this, SLOT(slotEditBpmScheme())); |
3815 | - connect(btnDelete, SIGNAL(pressed()), this, SLOT(slotDeleteBpmScheme())); |
3816 | - connect(btnDefault, SIGNAL(pressed()), this, SLOT(slotDefaultBpmScheme())); |
3817 | - |
3818 | - |
3819 | - // Determine if the config value has already been set. If not, default to enabled |
3820 | - QString sBpmEnabled = config->getValueString(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled")); |
3821 | - if(sBpmEnabled.isNull() || sBpmEnabled.isEmpty()) |
3822 | - { |
3823 | - config->set(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled"), ConfigValue(1)); |
3824 | - } |
3825 | - |
3826 | - // Set default value for analyze mode check box |
3827 | - int iBpmEnabled = config->getValueString(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled")).toInt(); |
3828 | - if (iBpmEnabled) |
3829 | - chkEnableBpmDetection->setChecked(true); |
3830 | - else |
3831 | - chkEnableBpmDetection->setChecked(false); |
3832 | - |
3833 | - int iBpmAboveRange = config->getValueString(ConfigKey(CONFIG_KEY,"BPMAboveRangeEnabled")).toInt(); |
3834 | - if (iBpmAboveRange) |
3835 | - chkAboveRange->setChecked(true); |
3836 | - else |
3837 | - chkAboveRange->setChecked(false); |
3838 | - |
3839 | - // Set default value for detect BPM on import check box |
3840 | - int iDetectBpmOnImport = config->getValueString(ConfigKey(CONFIG_KEY,"DetectBPMOnImport")).toInt(); |
3841 | - if (iDetectBpmOnImport) |
3842 | - chkDetectOnImport->setChecked(true); |
3843 | - else |
3844 | - chkDetectOnImport->setChecked(false); |
3845 | - |
3846 | - // Set default value for write ID3 tag check box |
3847 | - int iWriteID3Tag = config->getValueString(ConfigKey(CONFIG_KEY,"WriteID3Tag")).toInt(); |
3848 | - if (iWriteID3Tag) |
3849 | - chkWriteID3->setChecked(true); |
3850 | - else |
3851 | - chkWriteID3->setChecked(false); |
3852 | - |
3853 | - chkWriteID3->setEnabled(false); |
3854 | - chkDetectOnImport->setEnabled(false); |
3855 | - |
3856 | - // Load the BPM schemes |
3857 | - loadBpmSchemes(); |
3858 | - populateBpmSchemeList(); |
3859 | - |
3860 | - updateBpmEnabled(); |
3861 | - |
3862 | - |
3863 | - //Load BPM Range Values |
3864 | - /*int iRangeStart = config->getValueString(ConfigKey("[BPM]","BPMRangeStart")).toInt(); |
3865 | - if(iRangeStart > 0 && iRangeStart <= 220) |
3866 | - spinBoxBPMRangeStart->setValue(iRangeStart); |
3867 | - else |
3868 | - spinBoxBPMRangeStart->setValue(60); |
3869 | - |
3870 | - int iRangeEnd = config->getValueString(ConfigKey("[BPM]","BPMRangeEnd")).toInt(); |
3871 | - if(iRangeEnd > 0 && iRangeEnd <=220) |
3872 | - spinBoxBPMRangeEnd->setValue(iRangeEnd); |
3873 | - else |
3874 | - spinBoxBPMRangeEnd->setValue(180);*/ |
3875 | - |
3876 | -} |
3877 | - |
3878 | -DlgPrefBpm::~DlgPrefBpm() |
3879 | -{ |
3880 | - saveBpmSchemes(); |
3881 | - |
3882 | - while (!m_BpmSchemes.isEmpty()) |
3883 | - { |
3884 | - delete m_BpmSchemes.takeFirst(); |
3885 | - } |
3886 | -} |
3887 | - |
3888 | -void DlgPrefBpm::slotSetBpmDetectOnImport(int) |
3889 | -{ |
3890 | - if (chkDetectOnImport->isChecked()) |
3891 | - config->set(ConfigKey(CONFIG_KEY,"DetectBPMOnImport"), ConfigValue(1)); |
3892 | - else |
3893 | - config->set(ConfigKey(CONFIG_KEY,"DetectBPMOnImport"), ConfigValue(0)); |
3894 | -} |
3895 | - |
3896 | -void DlgPrefBpm::slotSetWriteID3Tag(int) |
3897 | -{ |
3898 | - if (chkWriteID3->isChecked()) |
3899 | - config->set(ConfigKey(CONFIG_KEY,"WriteID3Tag"), ConfigValue(1)); |
3900 | - else |
3901 | - config->set(ConfigKey(CONFIG_KEY,"WriteID3Tag"), ConfigValue(0)); |
3902 | -} |
3903 | - |
3904 | -void DlgPrefBpm::slotSetBpmEnabled(int) |
3905 | -{ |
3906 | - if (chkEnableBpmDetection->isChecked()) |
3907 | - config->set(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled"), ConfigValue(1)); |
3908 | - else |
3909 | - config->set(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled"), ConfigValue(0)); |
3910 | - |
3911 | - updateBpmEnabled(); |
3912 | - |
3913 | -} |
3914 | - |
3915 | -void DlgPrefBpm::slotSetAboveRange(int) { |
3916 | - if (chkAboveRange->isChecked()) |
3917 | - config->set(ConfigKey(CONFIG_KEY,"BPMAboveRangeEnabled"), ConfigValue(1)); |
3918 | - else |
3919 | - config->set(ConfigKey(CONFIG_KEY,"BPMAboveRangeEnabled"), ConfigValue(0)); |
3920 | -} |
3921 | - |
3922 | -void DlgPrefBpm::slotSetBpmRangeStart(int begin) |
3923 | -{ |
3924 | - Q_UNUSED(begin); |
3925 | - //config->set(ConfigKey("[BPM]","BPMRangeStart"),ConfigValue(begin)); |
3926 | -} |
3927 | - |
3928 | -void DlgPrefBpm::slotSetBpmRangeEnd(int end) |
3929 | -{ |
3930 | - Q_UNUSED(end); |
3931 | - //config->set(ConfigKey("[BPM]","BPMRangeEnd"),ConfigValue(end)); |
3932 | -} |
3933 | - |
3934 | -void DlgPrefBpm::slotEditBpmScheme() |
3935 | -{ |
3936 | - int row = lstSchemes->currentRow(); |
3937 | - |
3938 | - if(row > -1) |
3939 | - { |
3940 | - BpmScheme *schemeToEdit = m_BpmSchemes.at(row); |
3941 | - QString oldname = schemeToEdit->getName(); |
3942 | - |
3943 | - // Open the BPM scheme dialog to edit |
3944 | - DlgBpmScheme* SchemeEdit = new DlgBpmScheme(schemeToEdit); |
3945 | - SchemeEdit->setModal(true); |
3946 | - SchemeEdit->exec(); |
3947 | - |
3948 | - QListWidgetItem *item = lstSchemes->item(row); |
3949 | - item->setText(schemeToEdit->getName()); |
3950 | - |
3951 | - if(oldname == config->getValueString(ConfigKey("[BPM]","DefaultScheme"))) |
3952 | - { |
3953 | - config->set(ConfigKey("[BPM]","DefaultScheme"), schemeToEdit->getName()); |
3954 | - } |
3955 | - } |
3956 | -} |
3957 | - |
3958 | -void DlgPrefBpm::slotAddBpmScheme() |
3959 | -{ |
3960 | - BpmScheme *schemeToAdd = NULL; |
3961 | - |
3962 | - // Open the BPM scheme dialog to add |
3963 | - DlgBpmScheme* SchemeEdit = new DlgBpmScheme(schemeToAdd); |
3964 | - SchemeEdit->setModal(true); |
3965 | - |
3966 | - if(SchemeEdit->exec() == QDialog::Accepted) |
3967 | - { |
3968 | - if(schemeToAdd) |
3969 | - { |
3970 | - m_BpmSchemes.push_back(schemeToAdd); |
3971 | - QListWidgetItem *addScheme = new QListWidgetItem(lstSchemes); |
3972 | - addScheme->setText(schemeToAdd->getName()); |
3973 | - } |
3974 | - } |
3975 | - else |
3976 | - { |
3977 | - delete schemeToAdd; |
3978 | - } |
3979 | - |
3980 | - |
3981 | -} |
3982 | - |
3983 | -void DlgPrefBpm::slotDeleteBpmScheme() |
3984 | -{ |
3985 | - int row = lstSchemes->currentRow(); |
3986 | - |
3987 | - if(row > -1) |
3988 | - { |
3989 | - qDebug() << "Removing Bpm Scheme at position " << row; |
3990 | - delete lstSchemes->takeItem(row); |
3991 | - m_BpmSchemes.removeAt(row); |
3992 | - } |
3993 | -} |
3994 | - |
3995 | -void DlgPrefBpm::slotDefaultBpmScheme() |
3996 | -{ |
3997 | - int row = lstSchemes->currentRow(); |
3998 | - |
3999 | - if(row > -1) |
4000 | - { |
4001 | - BpmScheme* scheme = m_BpmSchemes.at(row); |
4002 | - |
4003 | - config->set(ConfigKey("[BPM]","BPMRangeEnd"),ConfigValue(scheme->getMaxBpm())); |
4004 | - config->set(ConfigKey("[BPM]","BPMRangeStart"),ConfigValue(scheme->getMinBpm())); |
4005 | - config->set(ConfigKey("[BPM]","AnalyzeEntireSong"),ConfigValue(scheme->getAnalyzeEntireSong())); |
4006 | - config->set(ConfigKey("[BPM]","DefaultScheme"), scheme->getName()); |
4007 | - |
4008 | - clearListIcons(); |
4009 | - |
4010 | - QListWidgetItem *item = lstSchemes->item(row); |
4011 | - item->setIcon(QIcon(":/images/preferences/ic_preferences_bpmdetect.png")); |
4012 | - } |
4013 | -} |
4014 | - |
4015 | -void DlgPrefBpm::clearListIcons() |
4016 | -{ |
4017 | - for(int i=0; i < lstSchemes->count(); ++i) |
4018 | - { |
4019 | - lstSchemes->item(i)->setIcon(QIcon("")); |
4020 | - } |
4021 | -} |
4022 | - |
4023 | -void DlgPrefBpm::slotApply() |
4024 | -{ |
4025 | - saveBpmSchemes(); |
4026 | -} |
4027 | - |
4028 | -void DlgPrefBpm::slotUpdate() |
4029 | -{ |
4030 | -} |
4031 | - |
4032 | -void DlgPrefBpm::updateBpmEnabled() |
4033 | -{ |
4034 | - int iBpmEnabled = config->getValueString(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled")).toInt(); |
4035 | - if (iBpmEnabled) |
4036 | - { |
4037 | - chkDetectOnImport->setEnabled(true); |
4038 | - chkWriteID3->setEnabled(true); |
4039 | - chkAboveRange->setEnabled(true); |
4040 | - grpBpmSchemes->setEnabled(true); |
4041 | - } |
4042 | - else |
4043 | - { |
4044 | - chkDetectOnImport->setEnabled(false); |
4045 | - chkWriteID3->setEnabled(false); |
4046 | - chkAboveRange->setEnabled(false); |
4047 | - grpBpmSchemes->setEnabled(false); |
4048 | - } |
4049 | - |
4050 | - // These are not implemented yet, so don't enable them |
4051 | - chkDetectOnImport->setEnabled(false); |
4052 | - chkWriteID3->setEnabled(false); |
4053 | - |
4054 | -} |
4055 | - |
4056 | -void DlgPrefBpm::loadBpmSchemes() |
4057 | -{ |
4058 | - // Verify path for xml track file. |
4059 | - QString schemeFileName = config->getValueString(ConfigKey("[BPM]","SchemeFile")); |
4060 | - if (schemeFileName.trimmed().isEmpty() | !QFile(schemeFileName).exists() ) { |
4061 | - schemeFileName = CmdlineArgs::Instance().getSettingsPath() + BPMSCHEME_FILE; |
4062 | - qDebug() << "BPM Scheme File ConfigKey not set or file missing... setting to"<< schemeFileName; |
4063 | - config->set(ConfigKey("[BPM]","SchemeFile"), schemeFileName); |
4064 | - config->Save(); |
4065 | - } |
4066 | - |
4067 | - QString location(config->getValueString(ConfigKey("[BPM]","SchemeFile"))); |
4068 | - qDebug() << "BpmSchemes::readXML" << location; |
4069 | - |
4070 | - // Open XML file |
4071 | - QFile file(location); |
4072 | - |
4073 | - // Check if we can open the file |
4074 | - if (!file.exists()) |
4075 | - { |
4076 | - qDebug() << "BPM Scheme:" << location << "does not exist."; |
4077 | - file.close(); |
4078 | - return; |
4079 | - } |
4080 | - |
4081 | - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { |
4082 | - qDebug() << "BPM Scheme:" << location << "can't open file for reading."; |
4083 | - return; |
4084 | - } |
4085 | - |
4086 | - QByteArray fileData = file.readAll(); |
4087 | - QByteArray badHeader = QByteArray("<?xml version=\"1.0\" encoding=\"UTF-16\"?>"); |
4088 | - QByteArray goodHeader = QByteArray("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); |
4089 | - |
4090 | - // We've been writing UTF-16 as the encoding forever but actually writing |
4091 | - // the file in UTF-8 (well, latin1 actually). Qt seems to have started |
4092 | - // caring recently. Manually fix the header if we are dealing with an old |
4093 | - // file. |
4094 | - fileData.replace(badHeader, goodHeader); |
4095 | - |
4096 | - QDomDocument domXML("Mixxx_BPM_Scheme_List"); |
4097 | - |
4098 | - |
4099 | - |
4100 | - // Check if there is a parsing problem |
4101 | - QString error_msg; |
4102 | - int error_line; |
4103 | - int error_column; |
4104 | - if (!domXML.setContent(fileData, &error_msg, &error_line, &error_column)) |
4105 | - { |
4106 | - qDebug() << "BPM Scheme Parse error in" << location; |
4107 | - qDebug() << "Doctype:" << domXML.doctype().name(); |
4108 | - qDebug() << error_msg << "on line" << error_line << ", column" << error_column; |
4109 | - file.close(); |
4110 | - return; |
4111 | - } |
4112 | - |
4113 | - file.close(); |
4114 | - |
4115 | - // Get the root element |
4116 | - QDomElement elementRoot = domXML.documentElement(); |
4117 | - |
4118 | - // Get version |
4119 | - //int version = XmlParse::selectNodeInt(elementRoot, "Version"); |
4120 | - |
4121 | - // Get all the BPM schemes written in the xml file: |
4122 | - QDomNode node = XmlParse::selectNode(elementRoot, "Schemes").firstChild(); |
4123 | - BpmScheme* bpmScheme; //Current BPM Scheme |
4124 | - while (!node.isNull()) |
4125 | - { |
4126 | - if (node.isElement() && node.nodeName()=="Scheme") |
4127 | - { |
4128 | - bpmScheme = new BpmScheme(); |
4129 | - //Create the playlists internally. |
4130 | - //If the playlist is "Library" or "Play Queue", insert it into |
4131 | - //a special spot in the list of playlists. |
4132 | - bpmScheme->setName(XmlParse::selectNodeQString(node, "Name")); |
4133 | - bpmScheme->setMinBpm(XmlParse::selectNodeQString(node, "MinBpm").toInt()); |
4134 | - bpmScheme->setMaxBpm(XmlParse::selectNodeQString(node, "MaxBpm").toInt()); |
4135 | - bpmScheme->setAnalyzeEntireSong((bool)XmlParse::selectNodeQString(node, |
4136 | - "AnalyzeEntireSong").toInt()); |
4137 | - bpmScheme->setComment(XmlParse::selectNodeQString(node, "Comment")); |
4138 | - |
4139 | - m_BpmSchemes.push_back(bpmScheme); |
4140 | - } |
4141 | - |
4142 | - node = node.nextSibling(); |
4143 | - } |
4144 | - |
4145 | - if(m_BpmSchemes.size() == 0) |
4146 | - { |
4147 | - BpmScheme *scheme = new BpmScheme("Default", 70, 140, false); |
4148 | - m_BpmSchemes.push_back(scheme); |
4149 | - config->set(ConfigKey("[BPM]","DefaultScheme"), QString("Default")); |
4150 | - config->set(ConfigKey("[BPM]","BPMRangeEnd"),ConfigValue(scheme->getMaxBpm())); |
4151 | - config->set(ConfigKey("[BPM]","BPMRangeStart"),ConfigValue(scheme->getMinBpm())); |
4152 | - config->set(ConfigKey("[BPM]","AnalyzeEntireSong"),ConfigValue(scheme->getAnalyzeEntireSong())); |
4153 | - } |
4154 | -} |
4155 | - |
4156 | -void DlgPrefBpm::saveBpmSchemes() |
4157 | -{ |
4158 | - QString location(config->getValueString(ConfigKey("[BPM]","SchemeFile"))); |
4159 | - |
4160 | - // Create the xml document: |
4161 | - QDomDocument domXML( "Mixxx_BPM_Scheme_List" ); |
4162 | - |
4163 | - // Ensure UTF16 encoding |
4164 | - domXML.appendChild(domXML.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"")); |
4165 | - |
4166 | - // Set the document type |
4167 | - QDomElement elementRoot = domXML.createElement( "Mixxx_BPM_Scheme_List" ); |
4168 | - domXML.appendChild(elementRoot); |
4169 | - |
4170 | - // Add version information: |
4171 | - //XmlParse::addElement(domXML, elementRoot, "Version", QString("%1").arg(TRACK_VERSION)); |
4172 | - |
4173 | - // Write playlists |
4174 | - QDomElement schemesroot = domXML.createElement("Schemes"); |
4175 | - |
4176 | - QListIterator<BpmScheme*> it(m_BpmSchemes); |
4177 | - BpmScheme* current; |
4178 | - while (it.hasNext()) |
4179 | - { |
4180 | - current = it.next(); |
4181 | - |
4182 | - QDomElement elementNew = domXML.createElement("Scheme"); |
4183 | - current->writeXML(domXML, elementNew); |
4184 | - schemesroot.appendChild(elementNew); |
4185 | - |
4186 | - } |
4187 | - elementRoot.appendChild(schemesroot); |
4188 | - |
4189 | - // Open the file: |
4190 | - QFile opmlFile(location); |
4191 | - if (!opmlFile.open(QIODevice::WriteOnly)) |
4192 | - { |
4193 | - QMessageBox::critical(0, |
4194 | - tr("Error"), |
4195 | - tr("Cannot open file %1").arg(location)); |
4196 | - return; |
4197 | - } |
4198 | - // QByteArray encoded in UTF-8 |
4199 | - QByteArray ba = domXML.toByteArray(); |
4200 | - opmlFile.write(ba.constData(), ba.size()); |
4201 | - opmlFile.close(); |
4202 | -} |
4203 | - |
4204 | -void DlgPrefBpm::populateBpmSchemeList() |
4205 | -{ |
4206 | - QString defaultscheme = config->getValueString(ConfigKey("[BPM]","DefaultScheme")); |
4207 | - |
4208 | - for(int i=0; i < m_BpmSchemes.size(); ++i) |
4209 | - { |
4210 | - QListWidgetItem* scheme = new QListWidgetItem(lstSchemes); |
4211 | - scheme->setText(m_BpmSchemes.at(i)->getName()); |
4212 | - if(m_BpmSchemes.at(i)->getName() == defaultscheme) |
4213 | - { |
4214 | - scheme->setIcon(QIcon(":/images/preferences/ic_preferences_bpmdetect.png")); |
4215 | - } |
4216 | - } |
4217 | -} |
4218 | |
4219 | === removed file 'mixxx/src/dlgprefbpm.h' |
4220 | --- mixxx/src/dlgprefbpm.h 2008-05-11 15:27:38 +0000 |
4221 | +++ mixxx/src/dlgprefbpm.h 1970-01-01 00:00:00 +0000 |
4222 | @@ -1,67 +0,0 @@ |
4223 | - |
4224 | - |
4225 | -/*************************************************************************** |
4226 | - * * |
4227 | - * This program is free software; you can redistribute it and/or modify * |
4228 | - * it under the terms of the GNU General Public License as published by * |
4229 | - * the Free Software Foundation; either version 2 of the License, or * |
4230 | - * (at your option) any later version. * |
4231 | - * * |
4232 | - ***************************************************************************/ |
4233 | - |
4234 | -#ifndef DLGPREFBPM_H |
4235 | -#define DLGPREFBPM_H |
4236 | - |
4237 | -#include "ui_dlgprefbpmdlg.h" |
4238 | -#include "configobject.h" |
4239 | - |
4240 | -#include <qlist.h> |
4241 | - |
4242 | -class QWidget; |
4243 | -class BpmScheme; |
4244 | - |
4245 | -class DlgPrefBpm : public QWidget, Ui::DlgPrefBPMDlg { |
4246 | - Q_OBJECT |
4247 | -public: |
4248 | - DlgPrefBpm(QWidget *parent, ConfigObject<ConfigValue> *_config); |
4249 | - ~DlgPrefBpm(); |
4250 | -public slots: |
4251 | - |
4252 | - void slotSetBpmDetectOnImport(int); |
4253 | - void slotSetWriteID3Tag(int); |
4254 | - void slotSetBpmEnabled(int); |
4255 | - void slotSetBpmRangeStart(int); |
4256 | - void slotSetBpmRangeEnd(int); |
4257 | - void slotSetAboveRange(int); |
4258 | - |
4259 | - void slotEditBpmScheme(); |
4260 | - void slotAddBpmScheme(); |
4261 | - void slotDeleteBpmScheme(); |
4262 | - void slotDefaultBpmScheme(); |
4263 | - |
4264 | - /** Apply changes to widget */ |
4265 | - void slotApply(); |
4266 | - void slotUpdate(); |
4267 | -signals: |
4268 | - void apply(const QString &); |
4269 | -private: |
4270 | - |
4271 | - void clearListIcons(); |
4272 | - |
4273 | - // Determines whether or not to gray out the preferences |
4274 | - void updateBpmEnabled(); |
4275 | - |
4276 | - // Private methods for loading and saving the BPM schemes |
4277 | - // to and from the file system. |
4278 | - void loadBpmSchemes(); |
4279 | - void saveBpmSchemes(); |
4280 | - |
4281 | - // Method for filling in the list of BPM schemes on the dialog |
4282 | - void populateBpmSchemeList(); |
4283 | - |
4284 | - /** Pointer to config object */ |
4285 | - ConfigObject<ConfigValue> *config; |
4286 | - QList<BpmScheme*> m_BpmSchemes; |
4287 | -}; |
4288 | - |
4289 | -#endif |
4290 | |
4291 | === removed file 'mixxx/src/dlgprefbpmdlg.ui' |
4292 | --- mixxx/src/dlgprefbpmdlg.ui 2012-04-30 18:38:29 +0000 |
4293 | +++ mixxx/src/dlgprefbpmdlg.ui 1970-01-01 00:00:00 +0000 |
4294 | @@ -1,141 +0,0 @@ |
4295 | -<?xml version="1.0" encoding="UTF-8"?> |
4296 | -<ui version="4.0"> |
4297 | - <class>DlgPrefBPMDlg</class> |
4298 | - <widget class="QWidget" name="DlgPrefBPMDlg"> |
4299 | - <property name="geometry"> |
4300 | - <rect> |
4301 | - <x>0</x> |
4302 | - <y>0</y> |
4303 | - <width>433</width> |
4304 | - <height>446</height> |
4305 | - </rect> |
4306 | - </property> |
4307 | - <property name="windowTitle"> |
4308 | - <string>BPM Detection Settings</string> |
4309 | - </property> |
4310 | - <layout class="QVBoxLayout" name="verticalLayout"> |
4311 | - <item> |
4312 | - <widget class="QGroupBox" name="groupBox"> |
4313 | - <property name="title"> |
4314 | - <string>BPM Detection</string> |
4315 | - </property> |
4316 | - <layout class="QVBoxLayout" name="verticalLayout_2"> |
4317 | - <item> |
4318 | - <widget class="QCheckBox" name="chkEnableBpmDetection"> |
4319 | - <property name="text"> |
4320 | - <string>Enable BPM Detection</string> |
4321 | - </property> |
4322 | - </widget> |
4323 | - </item> |
4324 | - <item> |
4325 | - <widget class="Line" name="line1"> |
4326 | - <property name="frameShape"> |
4327 | - <enum>QFrame::HLine</enum> |
4328 | - </property> |
4329 | - <property name="frameShadow"> |
4330 | - <enum>QFrame::Sunken</enum> |
4331 | - </property> |
4332 | - </widget> |
4333 | - </item> |
4334 | - <item> |
4335 | - <widget class="QCheckBox" name="chkDetectOnImport"> |
4336 | - <property name="text"> |
4337 | - <string>Detect Tracks BPM on Import</string> |
4338 | - </property> |
4339 | - </widget> |
4340 | - </item> |
4341 | - <item> |
4342 | - <widget class="QCheckBox" name="chkWriteID3"> |
4343 | - <property name="text"> |
4344 | - <string>Write BPM to ID3 Tag</string> |
4345 | - </property> |
4346 | - </widget> |
4347 | - </item> |
4348 | - <item> |
4349 | - <widget class="QCheckBox" name="chkAboveRange"> |
4350 | - <property name="toolTip"> |
4351 | - <string>If BPM can be detected but not within specified range</string> |
4352 | - </property> |
4353 | - <property name="text"> |
4354 | - <string>Allow BPM above the range</string> |
4355 | - </property> |
4356 | - </widget> |
4357 | - </item> |
4358 | - </layout> |
4359 | - </widget> |
4360 | - </item> |
4361 | - <item> |
4362 | - <widget class="QGroupBox" name="grpBpmSchemes"> |
4363 | - <property name="minimumSize"> |
4364 | - <size> |
4365 | - <width>409</width> |
4366 | - <height>200</height> |
4367 | - </size> |
4368 | - </property> |
4369 | - <property name="title"> |
4370 | - <string>BPM Schemes</string> |
4371 | - </property> |
4372 | - <layout class="QGridLayout"> |
4373 | - <item row="4" column="1"> |
4374 | - <spacer> |
4375 | - <property name="orientation"> |
4376 | - <enum>Qt::Vertical</enum> |
4377 | - </property> |
4378 | - <property name="sizeHint" stdset="0"> |
4379 | - <size> |
4380 | - <width>20</width> |
4381 | - <height>40</height> |
4382 | - </size> |
4383 | - </property> |
4384 | - </spacer> |
4385 | - </item> |
4386 | - <item row="0" column="0" rowspan="5"> |
4387 | - <widget class="QListWidget" name="lstSchemes"> |
4388 | - <property name="showDropIndicator" stdset="0"> |
4389 | - <bool>false</bool> |
4390 | - </property> |
4391 | - <property name="dragDropMode"> |
4392 | - <enum>QAbstractItemView::NoDragDrop</enum> |
4393 | - </property> |
4394 | - <property name="modelColumn"> |
4395 | - <number>0</number> |
4396 | - </property> |
4397 | - </widget> |
4398 | - </item> |
4399 | - <item row="0" column="1"> |
4400 | - <widget class="QPushButton" name="btnAdd"> |
4401 | - <property name="text"> |
4402 | - <string>Add</string> |
4403 | - </property> |
4404 | - </widget> |
4405 | - </item> |
4406 | - <item row="1" column="1"> |
4407 | - <widget class="QPushButton" name="btnEdit"> |
4408 | - <property name="text"> |
4409 | - <string>Edit</string> |
4410 | - </property> |
4411 | - </widget> |
4412 | - </item> |
4413 | - <item row="2" column="1"> |
4414 | - <widget class="QPushButton" name="btnDelete"> |
4415 | - <property name="text"> |
4416 | - <string>Delete</string> |
4417 | - </property> |
4418 | - </widget> |
4419 | - </item> |
4420 | - <item row="3" column="1"> |
4421 | - <widget class="QPushButton" name="btnDefault"> |
4422 | - <property name="text"> |
4423 | - <string>Default</string> |
4424 | - </property> |
4425 | - </widget> |
4426 | - </item> |
4427 | - </layout> |
4428 | - </widget> |
4429 | - </item> |
4430 | - </layout> |
4431 | - </widget> |
4432 | - <layoutdefault spacing="6" margin="11"/> |
4433 | - <resources/> |
4434 | - <connections/> |
4435 | -</ui> |
4436 | |
4437 | === modified file 'mixxx/src/dlgprefeq.cpp' |
4438 | --- mixxx/src/dlgprefeq.cpp 2012-04-29 15:54:21 +0000 |
4439 | +++ mixxx/src/dlgprefeq.cpp 2013-05-16 01:44:29 +0000 |
4440 | @@ -15,8 +15,6 @@ |
4441 | * * |
4442 | ***************************************************************************/ |
4443 | |
4444 | -#include "dlgprefeq.h" |
4445 | -#include "engine/enginefilteriir.h" |
4446 | #include <qlineedit.h> |
4447 | #include <qwidget.h> |
4448 | #include <qslider.h> |
4449 | @@ -28,6 +26,10 @@ |
4450 | |
4451 | #include <assert.h> |
4452 | |
4453 | +#include "dlgprefeq.h" |
4454 | +#include "engine/enginefilteriir.h" |
4455 | +#include "controlobject.h" |
4456 | + |
4457 | #define CONFIG_KEY "[Mixer Profile]" |
4458 | |
4459 | const int kFrequencyUpperLimit = 20050; |
4460 | |
4461 | === modified file 'mixxx/src/dlgprefeq.h' |
4462 | --- mixxx/src/dlgprefeq.h 2011-12-06 19:40:07 +0000 |
4463 | +++ mixxx/src/dlgprefeq.h 2013-05-16 01:44:29 +0000 |
4464 | @@ -21,7 +21,7 @@ |
4465 | #include "ui_dlgprefeqdlg.h" |
4466 | #include "configobject.h" |
4467 | #include "engine/enginefilterblock.h" |
4468 | -#include "controlobject.h" |
4469 | +#include "controlobjectthread.h" |
4470 | |
4471 | class QWidget; |
4472 | /** |
4473 | |
4474 | === modified file 'mixxx/src/dlgpreferences.cpp' |
4475 | --- mixxx/src/dlgpreferences.cpp 2013-03-14 18:29:16 +0000 |
4476 | +++ mixxx/src/dlgpreferences.cpp 2013-05-16 01:44:29 +0000 |
4477 | @@ -31,11 +31,7 @@ |
4478 | #ifdef __SHOUTCAST__ |
4479 | #include "dlgprefshoutcast.h" |
4480 | #endif |
4481 | -#ifdef __VAMP__ |
4482 | - #include "dlgprefbeats.h" |
4483 | -#else |
4484 | - #include "dlgprefbpm.h" |
4485 | -#endif |
4486 | +#include "dlgprefbeats.h" |
4487 | |
4488 | #ifdef __MODPLUG__ |
4489 | #include "dlgprefmodplug.h" |
4490 | @@ -91,13 +87,8 @@ |
4491 | m_wcrossfader = new DlgPrefCrossfader(this, config); |
4492 | addPageWidget(m_wcrossfader); |
4493 | |
4494 | -#ifdef __VAMP__ |
4495 | m_wbeats = new DlgPrefBeats(this, config); |
4496 | addPageWidget (m_wbeats); |
4497 | -#else |
4498 | - m_wbpm = new DlgPrefBpm(this, config); |
4499 | - addPageWidget(m_wbpm); |
4500 | -#endif |
4501 | m_wreplaygain = new DlgPrefReplayGain(this, config); |
4502 | addPageWidget(m_wreplaygain); |
4503 | m_wrecord = new DlgPrefRecord(this, config); |
4504 | @@ -139,13 +130,8 @@ |
4505 | connect(this, SIGNAL(showDlg()), m_weq, SLOT(slotUpdate())); |
4506 | connect(this, SIGNAL(showDlg()), m_wcrossfader, SLOT(slotUpdate())); |
4507 | |
4508 | -#ifdef __VAMP__ |
4509 | connect(this, SIGNAL(showDlg()), |
4510 | m_wbeats, SLOT(slotUpdate())); |
4511 | -#else |
4512 | - connect(this, SIGNAL(showDlg()), |
4513 | - m_wbpm, SLOT(slotUpdate())); |
4514 | -#endif |
4515 | |
4516 | connect(this, SIGNAL(showDlg()), m_wreplaygain,SLOT(slotUpdate())); |
4517 | connect(this, SIGNAL(showDlg()), m_wrecord, SLOT(slotUpdate())); |
4518 | @@ -175,11 +161,7 @@ |
4519 | connect(buttonBox, SIGNAL(accepted()), m_wcrossfader,SLOT(slotApply())); |
4520 | connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotApply())); |
4521 | |
4522 | -#ifdef __VAMP__ |
4523 | connect(buttonBox, SIGNAL(accepted()), m_wbeats, SLOT(slotApply())); |
4524 | -#else |
4525 | - connect(buttonBox, SIGNAL(accepted()), m_wbpm, SLOT(slotApply())); |
4526 | -#endif |
4527 | connect(buttonBox, SIGNAL(accepted()), m_wreplaygain,SLOT(slotApply())); |
4528 | connect(buttonBox, SIGNAL(accepted()), m_wrecord, SLOT(slotApply())); |
4529 | #ifdef __SHOUTCAST__ |
4530 | @@ -247,19 +229,11 @@ |
4531 | m_pRecordingButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); |
4532 | |
4533 | |
4534 | -#ifdef __VAMP__ |
4535 | m_pAnalysersButton = new QTreeWidgetItem(contentsTreeWidget, QTreeWidgetItem::Type); |
4536 | m_pAnalysersButton->setIcon(0, QIcon(":/images/preferences/ic_preferences_bpmdetect.png")); |
4537 | m_pAnalysersButton->setText(0, tr("Beat Detection")); |
4538 | m_pAnalysersButton->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter); |
4539 | m_pAnalysersButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); |
4540 | -#else |
4541 | - m_pBPMdetectButton = new QTreeWidgetItem(contentsTreeWidget, QTreeWidgetItem::Type); |
4542 | - m_pBPMdetectButton->setIcon(0, QIcon(":/images/preferences/ic_preferences_bpmdetect.png")); |
4543 | - m_pBPMdetectButton->setText(0, tr("BPM Detection")); |
4544 | - m_pBPMdetectButton->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter); |
4545 | - m_pBPMdetectButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); |
4546 | -#endif |
4547 | m_pReplayGainButton = new QTreeWidgetItem(contentsTreeWidget, QTreeWidgetItem::Type); |
4548 | m_pReplayGainButton->setIcon(0, QIcon(":/images/preferences/ic_preferences_replaygain.png")); |
4549 | m_pReplayGainButton->setText(0, tr("Normalization")); |
4550 | @@ -323,14 +297,8 @@ |
4551 | pagesWidget->setCurrentWidget(m_wcrossfader->parentWidget()->parentWidget()); |
4552 | } else if (current == m_pRecordingButton) { |
4553 | pagesWidget->setCurrentWidget(m_wrecord->parentWidget()->parentWidget()); |
4554 | - |
4555 | -#ifdef __VAMP__ |
4556 | } else if (current == m_pAnalysersButton ) { |
4557 | pagesWidget->setCurrentWidget(m_wbeats->parentWidget()->parentWidget()); |
4558 | -#else |
4559 | - } else if (current == m_pBPMdetectButton) { |
4560 | - pagesWidget->setCurrentWidget(m_wbpm->parentWidget()->parentWidget()); |
4561 | -#endif |
4562 | } else if (current == m_pReplayGainButton) { |
4563 | pagesWidget->setCurrentWidget(m_wreplaygain->parentWidget()->parentWidget()); |
4564 | |
4565 | |
4566 | === modified file 'mixxx/src/dlgpreferences.h' |
4567 | --- mixxx/src/dlgpreferences.h 2013-03-14 17:43:39 +0000 |
4568 | +++ mixxx/src/dlgpreferences.h 2013-05-16 01:44:29 +0000 |
4569 | @@ -35,7 +35,6 @@ |
4570 | class DlgPrefEQ; |
4571 | class DlgPrefCrossfader; |
4572 | class DlgPrefRecord; |
4573 | -class DlgPrefBpm; |
4574 | class DlgPrefBeats; |
4575 | class DlgPrefVinyl; |
4576 | class DlgPrefNoVinyl; |
4577 | @@ -90,7 +89,6 @@ |
4578 | DlgPrefEQ* m_weq; |
4579 | DlgPrefCrossfader* m_wcrossfader; |
4580 | DlgPrefRecord* m_wrecord; |
4581 | - DlgPrefBpm* m_wbpm; |
4582 | DlgPrefBeats* m_wbeats; |
4583 | DlgPrefVinyl* m_wvinylcontrol; |
4584 | DlgPrefNoVinyl* m_wnovinylcontrol; |
4585 | |
4586 | === modified file 'mixxx/src/dlgprefrecord.cpp' |
4587 | --- mixxx/src/dlgprefrecord.cpp 2012-06-15 20:49:49 +0000 |
4588 | +++ mixxx/src/dlgprefrecord.cpp 2013-05-16 01:44:29 +0000 |
4589 | @@ -17,12 +17,12 @@ |
4590 | |
4591 | #include <QtCore> |
4592 | #include <QtGui> |
4593 | + |
4594 | #include "dlgprefrecord.h" |
4595 | #include "recording/defs_recording.h" |
4596 | #include "controlobject.h" |
4597 | #include "controlobjectthreadmain.h" |
4598 | -#include "recording/encoder.h" |
4599 | - |
4600 | +#include "encoder/encoder.h" |
4601 | |
4602 | DlgPrefRecord::DlgPrefRecord(QWidget * parent, ConfigObject<ConfigValue> * _config) |
4603 | : QWidget(parent) { |
4604 | @@ -39,12 +39,11 @@ |
4605 | recordControl = new ControlObjectThreadMain( |
4606 | ControlObject::getControl(ConfigKey(RECORDING_PREF_KEY, "status"))); |
4607 | |
4608 | -#ifdef __SHOUTCAST__ |
4609 | radioOgg = new QRadioButton("Ogg Vorbis"); |
4610 | radioMp3 = new QRadioButton(ENCODING_MP3); |
4611 | |
4612 | // Setting recordings path |
4613 | - QString recordingsPath = config->getValueString(ConfigKey("[Recording]","Directory")); |
4614 | + QString recordingsPath = config->getValueString(ConfigKey(RECORDING_PREF_KEY,"Directory")); |
4615 | if (recordingsPath == "") { |
4616 | // Initialize recordings path in config to old default path. |
4617 | // Do it here so we show current value in UI correctly. |
4618 | @@ -67,8 +66,6 @@ |
4619 | horizontalLayout->addWidget(radioOgg); |
4620 | horizontalLayout->addWidget(radioMp3); |
4621 | |
4622 | -#endif |
4623 | - |
4624 | //AIFF and WAVE are supported by default |
4625 | radioWav = new QRadioButton(ENCODING_WAVE); |
4626 | connect(radioWav, SIGNAL(clicked()), |
4627 | @@ -80,7 +77,6 @@ |
4628 | this, SLOT(slotApply())); |
4629 | horizontalLayout->addWidget(radioAiff); |
4630 | |
4631 | - |
4632 | #ifdef SF_FORMAT_FLAC |
4633 | radioFlac = new QRadioButton(ENCODING_FLAC); |
4634 | connect(radioFlac,SIGNAL(clicked()), |
4635 | @@ -89,18 +85,18 @@ |
4636 | #endif |
4637 | |
4638 | //Read config and check radio button |
4639 | - QString format = config->getValueString(ConfigKey("[Recording]","Encoding")); |
4640 | + QString format = config->getValueString(ConfigKey(RECORDING_PREF_KEY,"Encoding")); |
4641 | if(format == ENCODING_WAVE) |
4642 | radioWav->setChecked(true); |
4643 | -#ifdef __SHOUTCAST__ |
4644 | else if(format == ENCODING_OGG) |
4645 | radioOgg->setChecked(true); |
4646 | else if (format == ENCODING_MP3) |
4647 | radioMp3->setChecked(true); |
4648 | -#endif |
4649 | -#ifdef SF_FORMAT_FLAC |
4650 | else if (format == ENCODING_AIFF) |
4651 | radioAiff->setChecked(true); |
4652 | +#ifdef SF_FORMAT_FLAC |
4653 | + else if (format == ENCODING_FLAC) |
4654 | + radioFlac->setChecked(true); |
4655 | #endif |
4656 | else //Invalid, so set default and save |
4657 | { |
4658 | @@ -109,6 +105,8 @@ |
4659 | config->set(ConfigKey(RECORDING_PREF_KEY, "Encoding"), ConfigValue(ENCODING_WAVE)); |
4660 | } |
4661 | |
4662 | + loadMetaData(); |
4663 | + |
4664 | //Connections |
4665 | connect(SliderQuality, SIGNAL(valueChanged(int)), this, SLOT(slotSliderQuality())); |
4666 | connect(SliderQuality, SIGNAL(sliderMoved(int)), this, SLOT(slotSliderQuality())); |
4667 | @@ -125,7 +123,7 @@ |
4668 | comboBoxSplitting->addItem(SPLIT_2048MB); |
4669 | comboBoxSplitting->addItem(SPLIT_4096MB); |
4670 | |
4671 | - QString fileSizeStr = config->getValueString(ConfigKey("[Recording]","FileSize")); |
4672 | + QString fileSizeStr = config->getValueString(ConfigKey(RECORDING_PREF_KEY,"FileSize")); |
4673 | int index = comboBoxSplitting->findText(fileSizeStr); |
4674 | if(index > 0){ |
4675 | //set file split size |
4676 | @@ -134,7 +132,7 @@ |
4677 | //Otherwise 650 MB will be default file split size |
4678 | |
4679 | //Read CUEfile info |
4680 | - CheckBoxRecordCueFile->setChecked((bool) config->getValueString(ConfigKey("[Recording]","CueEnabled")).toInt()); |
4681 | + CheckBoxRecordCueFile->setChecked((bool) config->getValueString(ConfigKey(RECORDING_PREF_KEY,"CueEnabled")).toInt()); |
4682 | |
4683 | } |
4684 | |
4685 | @@ -243,7 +241,7 @@ |
4686 | void DlgPrefRecord::slotUpdate() |
4687 | { |
4688 | // Recordings path |
4689 | - QString recordingsPath = config->getValueString(ConfigKey("[Recording]","Directory")); |
4690 | + QString recordingsPath = config->getValueString(ConfigKey(RECORDING_PREF_KEY,"Directory")); |
4691 | LineEditRecordings->setText(recordingsPath); |
4692 | |
4693 | if (radioWav && radioWav->isChecked()) |
4694 | @@ -272,7 +270,7 @@ |
4695 | void DlgPrefRecord::slotBrowseRecordingsDir() |
4696 | { |
4697 | QString fd = QFileDialog::getExistingDirectory(this, tr("Choose recordings directory"), |
4698 | - config->getValueString(ConfigKey("[Recording]","Directory"))); |
4699 | + config->getValueString(ConfigKey(RECORDING_PREF_KEY,"Directory"))); |
4700 | if (fd != "") |
4701 | { |
4702 | LineEditRecordings->setText(fd); |
4703 | @@ -293,10 +291,10 @@ |
4704 | qDebug() << "Recordings path was empty in dialog"; |
4705 | return; |
4706 | } |
4707 | - if (LineEditRecordings->text() != config->getValueString(ConfigKey("[Recording]","Directory"))) |
4708 | + if (LineEditRecordings->text() != config->getValueString(ConfigKey(RECORDING_PREF_KEY,"Directory"))) |
4709 | { |
4710 | qDebug() << "Saved recordings path" << LineEditRecordings->text(); |
4711 | - config->set(ConfigKey("[Recording]","Directory"), LineEditRecordings->text()); |
4712 | + config->set(ConfigKey(RECORDING_PREF_KEY,"Directory"), LineEditRecordings->text()); |
4713 | } |
4714 | } |
4715 | |
4716 | |
4717 | === modified file 'mixxx/src/dlgprefshoutcast.h' |
4718 | --- mixxx/src/dlgprefshoutcast.h 2008-01-26 19:29:41 +0000 |
4719 | +++ mixxx/src/dlgprefshoutcast.h 2013-05-16 01:44:29 +0000 |
4720 | @@ -5,7 +5,7 @@ |
4721 | copyright : (C) 2008 by Wesley Stessens |
4722 | (C) 2007 by John Sully |
4723 | (C) 2008 by Albert Santoni |
4724 | - email : |
4725 | + email : |
4726 | ***************************************************************************/ |
4727 | |
4728 | /*************************************************************************** |
4729 | @@ -24,9 +24,7 @@ |
4730 | #include "controlobject.h" |
4731 | #include "configobject.h" |
4732 | #include "controlobjectthreadmain.h" |
4733 | - |
4734 | -#define SHOUTCAST_PREF_KEY "[Shoutcast]" |
4735 | -#define SHOUTCAST_DEFAULT_PORT "8000" |
4736 | +#include "shoutcast/defs_shoutcast.h" |
4737 | |
4738 | class QWidget; |
4739 | /** |
4740 | @@ -35,7 +33,7 @@ |
4741 | |
4742 | class DlgPrefShoutcast : public QWidget, public Ui::DlgPrefShoutcastDlg { |
4743 | Q_OBJECT |
4744 | -public: |
4745 | +public: |
4746 | DlgPrefShoutcast(QWidget *parent, ConfigObject<ConfigValue> *_config); |
4747 | ~DlgPrefShoutcast(); |
4748 | public slots: |
4749 | |
4750 | === modified file 'mixxx/src/dlgtrackinfo.h' |
4751 | --- mixxx/src/dlgtrackinfo.h 2010-09-10 06:04:12 +0000 |
4752 | +++ mixxx/src/dlgtrackinfo.h 2013-05-16 01:44:29 +0000 |
4753 | @@ -10,7 +10,15 @@ |
4754 | #include "ui_dlgtrackinfo.h" |
4755 | |
4756 | #include "trackinfoobject.h" |
4757 | -#include "controlbeat.h" |
4758 | + |
4759 | +/** Minimum allowed Beat per minute (BPM) */ |
4760 | +const int minBPM = 30; |
4761 | +/** Maximum allowed bpm */ |
4762 | +const int maxBPM = 240; |
4763 | +/** Maximum allowed interval between beats in milli seconds (calculated from minBPM) */ |
4764 | +const int maxInterval = (int)(1000.*(60./(CSAMPLE)minBPM)); |
4765 | +/** Filter length */ |
4766 | +const int filterLength = 5; |
4767 | |
4768 | class Cue; |
4769 | |
4770 | |
4771 | === added directory 'mixxx/src/encoder' |
4772 | === renamed file 'mixxx/src/recording/encoder.cpp' => 'mixxx/src/encoder/encoder.cpp' |
4773 | --- mixxx/src/recording/encoder.cpp 2010-11-01 17:24:48 +0000 |
4774 | +++ mixxx/src/encoder/encoder.cpp 2013-05-16 01:44:29 +0000 |
4775 | @@ -14,24 +14,11 @@ |
4776 | * * |
4777 | ***************************************************************************/ |
4778 | |
4779 | -#include <stdlib.h> // needed for random num gen |
4780 | -#include <time.h> // needed for random num gen |
4781 | -#include <string.h> // needed for memcpy |
4782 | -#include <QDebug> |
4783 | - |
4784 | -#include "engine/engineabstractrecord.h" |
4785 | -#include "controlobjectthreadmain.h" |
4786 | -#include "controlobject.h" |
4787 | -#include "playerinfo.h" |
4788 | -#include "trackinfoobject.h" |
4789 | - |
4790 | -#include "encoder.h" |
4791 | - |
4792 | -// Constructor |
4793 | +#include "encoder/encoder.h" |
4794 | + |
4795 | Encoder::Encoder() { |
4796 | } |
4797 | |
4798 | -// Destructor |
4799 | Encoder::~Encoder() { |
4800 | } |
4801 | |
4802 | |
4803 | === renamed file 'mixxx/src/recording/encoder.h' => 'mixxx/src/encoder/encoder.h' |
4804 | --- mixxx/src/recording/encoder.h 2010-09-07 07:50:15 +0000 |
4805 | +++ mixxx/src/encoder/encoder.h 2013-05-16 01:44:29 +0000 |
4806 | @@ -17,30 +17,20 @@ |
4807 | #ifndef ENCODER_H |
4808 | #define ENCODER_H |
4809 | |
4810 | -#include <stdlib.h> // needed for random num gen |
4811 | -#include <time.h> // needed for random num gen |
4812 | -#include <string.h> // needed for memcpy |
4813 | -#include <QDebug> |
4814 | - |
4815 | -#include "engine/engineabstractrecord.h" |
4816 | -#include "controlobjectthreadmain.h" |
4817 | -#include "controlobject.h" |
4818 | -#include "playerinfo.h" |
4819 | -#include "trackinfoobject.h" |
4820 | - |
4821 | - |
4822 | -class Encoder : public QObject { |
4823 | - Q_OBJECT |
4824 | - |
4825 | +#include "defs.h" |
4826 | + |
4827 | +class Encoder { |
4828 | public: |
4829 | Encoder(); |
4830 | virtual ~Encoder(); |
4831 | - /* |
4832 | - * General Encoder methods |
4833 | - */ |
4834 | - virtual int initEncoder(int bitrate) = 0; |
4835 | + |
4836 | + virtual int initEncoder(int bitrate, int samplerate) = 0; |
4837 | + // encodes the provided buffer of audio. |
4838 | virtual void encodeBuffer(const CSAMPLE *samples, const int size) = 0; |
4839 | + // Adds metadata to the encoded auio, i.e., the ID3 tag. Currently only used |
4840 | + // by EngineRecord, EngineShoutcast does something different. |
4841 | virtual void updateMetaData(char* artist, char* title, char* album) = 0; |
4842 | + // called at the end when encoding is finished |
4843 | virtual void flush() = 0; |
4844 | /**converts an OGG quality measure from 1..10 to a bitrate **/ |
4845 | static int convertToBitrate(int quality); |
4846 | |
4847 | === renamed file 'mixxx/src/engine/engineabstractrecord.h' => 'mixxx/src/encoder/encodercallback.h' |
4848 | --- mixxx/src/engine/engineabstractrecord.h 2011-03-22 16:24:04 +0000 |
4849 | +++ mixxx/src/encoder/encodercallback.h 2013-05-16 01:44:29 +0000 |
4850 | @@ -1,29 +1,12 @@ |
4851 | -/*************************************************************************** |
4852 | - engineabstractrecord.h - Abstract Recording class |
4853 | - ------------------- |
4854 | - copyright : (C) 2007 by Wesley Stessens |
4855 | - ***************************************************************************/ |
4856 | - |
4857 | -/*************************************************************************** |
4858 | - * * |
4859 | - * This program is free software; you can redistribute it and/or modify * |
4860 | - * it under the terms of the GNU General Public License as published by * |
4861 | - * the Free Software Foundation; either version 2 of the License, or * |
4862 | - * (at your option) any later version. * |
4863 | - * * |
4864 | - ***************************************************************************/ |
4865 | - |
4866 | -#ifndef ENGINEABSTRACTRECORD_H |
4867 | -#define ENGINEABSTRACTRECORD_H |
4868 | - |
4869 | -#include "defs.h" |
4870 | -#include "engine/engineobject.h" |
4871 | - |
4872 | -class EngineAbstractRecord : public EngineObject { |
4873 | +#ifndef ENCODERCALLBACK_H |
4874 | +#define ENCODERCALLBACK_H |
4875 | + |
4876 | +class EncoderCallback { |
4877 | public: |
4878 | - /** writes to encoded audio to a stream, e.g., a file stream or shoutcast stream **/ |
4879 | + // writes to encoded audio to a stream, e.g., a file stream or shoutcast stream |
4880 | virtual void write(unsigned char *header, unsigned char *body, |
4881 | - int headerLen, int bodyLen) = 0; |
4882 | + int headerLen, int bodyLen) = 0; |
4883 | }; |
4884 | |
4885 | -#endif |
4886 | +#endif /* ENCODERCALLBACK_H */ |
4887 | + |
4888 | |
4889 | === renamed file 'mixxx/src/recording/encodermp3.cpp' => 'mixxx/src/encoder/encodermp3.cpp' |
4890 | --- mixxx/src/recording/encodermp3.cpp 2012-05-14 20:47:43 +0000 |
4891 | +++ mixxx/src/encoder/encodermp3.cpp 2013-05-16 01:44:29 +0000 |
4892 | @@ -15,53 +15,20 @@ |
4893 | * * |
4894 | ***************************************************************************/ |
4895 | |
4896 | -#include <stdlib.h> // needed for random num |
4897 | -#include <time.h> // needed for random num |
4898 | -#include <string.h> // needed for memcpy |
4899 | -#include <QDebug> |
4900 | +#include <QtDebug> |
4901 | +#include <QObject> |
4902 | |
4903 | -#include "recording/encodermp3.h" |
4904 | -#include "engine/engineabstractrecord.h" |
4905 | -#include "controlobjectthreadmain.h" |
4906 | -#include "controlobject.h" |
4907 | -#include "playerinfo.h" |
4908 | -#include "trackinfoobject.h" |
4909 | -#include "defs_recording.h" |
4910 | +#include "encoder/encodermp3.h" |
4911 | +#include "encoder/encodercallback.h" |
4912 | #include "errordialoghandler.h" |
4913 | |
4914 | -EncoderMp3::EncoderMp3(EngineAbstractRecord *engine) { |
4915 | - m_pEngine = engine; |
4916 | - m_metaDataTitle = NULL; |
4917 | - m_metaDataArtist = NULL; |
4918 | - m_metaDataAlbum = NULL; |
4919 | - m_pMetaData = TrackPointer(NULL); |
4920 | - m_bufferIn[0] = NULL; |
4921 | - m_bufferIn[1] = NULL; |
4922 | - m_bufferOut = NULL; |
4923 | - m_bufferOutSize = 0; |
4924 | - m_lameFlags = NULL; |
4925 | - m_library = NULL; |
4926 | - m_samplerate = NULL; |
4927 | - |
4928 | - //These are the function pointers for lame |
4929 | - lame_init = 0; |
4930 | - lame_set_num_channels = 0; |
4931 | - lame_set_in_samplerate = 0; |
4932 | - lame_set_out_samplerate = 0; |
4933 | - lame_close = 0; |
4934 | - lame_set_brate = 0; |
4935 | - lame_set_mode = 0; |
4936 | - lame_set_quality = 0; |
4937 | - lame_set_bWriteVbrTag = 0; |
4938 | - lame_encode_buffer_float = 0; |
4939 | - lame_init_params = 0; |
4940 | - lame_encode_flush = 0; |
4941 | - |
4942 | - id3tag_init= 0; |
4943 | - id3tag_set_title = 0; |
4944 | - id3tag_set_artist = 0; |
4945 | - id3tag_set_album = 0; |
4946 | - |
4947 | +EncoderMp3::EncoderMp3(EncoderCallback* pCallback) |
4948 | + : m_lameFlags(NULL), |
4949 | + m_metaDataTitle(NULL), |
4950 | + m_metaDataArtist(NULL), |
4951 | + m_metaDataAlbum(NULL), |
4952 | + m_bufferOut(NULL), |
4953 | + m_bufferOutSize(0), |
4954 | /* |
4955 | * @ Author: Tobias Rafreider |
4956 | * Nobody has initialized the field before my code review. At runtime the |
4957 | @@ -78,7 +45,30 @@ |
4958 | * along with LAME. This bug was detected by using Valgrind memory analyser |
4959 | * |
4960 | */ |
4961 | - m_bufferInSize = 0; |
4962 | + m_bufferInSize(0), |
4963 | + m_pCallback(pCallback), |
4964 | + m_library(NULL) { |
4965 | + m_bufferIn[0] = NULL; |
4966 | + m_bufferIn[1] = NULL; |
4967 | + |
4968 | + //These are the function pointers for lame |
4969 | + lame_init = 0; |
4970 | + lame_set_num_channels = 0; |
4971 | + lame_set_in_samplerate = 0; |
4972 | + lame_set_out_samplerate = 0; |
4973 | + lame_close = 0; |
4974 | + lame_set_brate = 0; |
4975 | + lame_set_mode = 0; |
4976 | + lame_set_quality = 0; |
4977 | + lame_set_bWriteVbrTag = 0; |
4978 | + lame_encode_buffer_float = 0; |
4979 | + lame_init_params = 0; |
4980 | + lame_encode_flush = 0; |
4981 | + |
4982 | + id3tag_init= 0; |
4983 | + id3tag_set_title = 0; |
4984 | + id3tag_set_artist = 0; |
4985 | + id3tag_set_album = 0; |
4986 | |
4987 | /* |
4988 | * Load shared library |
4989 | @@ -86,7 +76,7 @@ |
4990 | QStringList libnames; |
4991 | QString libname = ""; |
4992 | #ifdef __LINUX__ |
4993 | - libnames << "mp3lame"; |
4994 | + libnames << "mp3lame"; |
4995 | #elif __WINDOWS__ |
4996 | libnames << "lame_enc.dll"; |
4997 | #elif __APPLE__ |
4998 | @@ -103,22 +93,21 @@ |
4999 | m_library = NULL; |
5000 | } |
I'm getting really excited about these control changes!
* Create a value wrapper around COBase values -- ControlNumericP rivate (CNP). /COTTRotary/ COPotmeter/ COLogpotmere/ COLinpotmeter/ etc. all used to have built in. valueFromWidget ).
* Add a static creation method / hash index of existing CNPs similar to CO.
* Add a ControlBehavior class hierarchy that encodes all the behaviors that CO/COPushButton
* Remove all value-space to parameter-space conversion methods from CO hierarchy (e.g. valueToWidget/
* Get rid of CO / COT proxying. CO and COT both refer to CNP now and are equals in the sense that they both make requests to CNP. The only difference is that CO also creates a CNP when it is created for the first time and sets its behavior while a COT only binds to an existing CNP.
* Add valueChangedFro mEngine and valueChangedByThis signals to CO and COT respectively. You'll see that CNP solves the issue that was previously solved by the sync thread -- all mutations (add/sub/set/reset) to the CNP include a pointer to the setter. This is re-broadcast by the CNP and so CO/COT can check the pointer and choose to emit either valueChanged() or valueChangedFro mEngine/ valueChangedByT his().
I'm only keeping the name valueChangedFro mEngine name on the CO to keep backwards compatibility with other engine branches that are still unmerged (e.g. engine- control- refactor) .
I'm really liking where this is going. There is really no difference between CO and COT except the creation of a CNP and setting of a Behavior in the CO. We could easily swap this out with a static factory method like Control: :createPushButt on(options. ..) that returned a COT-style object (that we could finally rename as Control* to keep things shorter). We could also flatten the CO hierarchy if the behavior-setting was done by a factory/static method. ControlPotmeter is the only standout there since other parts of Mixxx introspect on the control using dynamic_cast. Those hacks should be replaced with something more generic at the CNP layer that lets you ask things about the behavior.