Merge lp://qastaging/~mixxxdevelopers/mixxx/features_controllerAbstraction into lp://qastaging/~mixxxdevelopers/mixxx/trunk

Proposed by RJ Skerry-Ryan
Status: Superseded
Proposed branch: lp://qastaging/~mixxxdevelopers/mixxx/features_controllerAbstraction
Merge into: lp://qastaging/~mixxxdevelopers/mixxx/trunk
Diff against target: 21632 lines (+11597/-8152)
153 files modified
mixxx/SConstruct (+1/-1)
mixxx/build/depends.py (+23/-22)
mixxx/build/features.py (+47/-34)
mixxx/lib/hidapi-0.7.0/LICENSE-orig.txt (+9/-0)
mixxx/lib/hidapi-0.7.0/LICENSE.txt (+13/-0)
mixxx/lib/hidapi-0.7.0/hidapi/hidapi.h (+383/-0)
mixxx/lib/hidapi-0.7.0/linux/.gitignore (+13/-0)
mixxx/lib/hidapi-0.7.0/linux/Makefile (+36/-0)
mixxx/lib/hidapi-0.7.0/linux/README.txt (+63/-0)
mixxx/lib/hidapi-0.7.0/linux/hid-libusb.c (+1386/-0)
mixxx/lib/hidapi-0.7.0/linux/hid.c (+595/-0)
mixxx/lib/hidapi-0.7.0/mac/.gitignore (+13/-0)
mixxx/lib/hidapi-0.7.0/mac/Makefile (+32/-0)
mixxx/lib/hidapi-0.7.0/mac/hid.c (+1122/-0)
mixxx/lib/hidapi-0.7.0/windows/.gitignore (+11/-0)
mixxx/lib/hidapi-0.7.0/windows/Makefile (+14/-0)
mixxx/lib/hidapi-0.7.0/windows/Makefile.mingw (+32/-0)
mixxx/lib/hidapi-0.7.0/windows/ddk_build/.gitignore (+2/-0)
mixxx/lib/hidapi-0.7.0/windows/ddk_build/hidapi.def (+17/-0)
mixxx/lib/hidapi-0.7.0/windows/ddk_build/makefile (+49/-0)
mixxx/lib/hidapi-0.7.0/windows/ddk_build/sources (+23/-0)
mixxx/lib/hidapi-0.7.0/windows/hid.c (+873/-0)
mixxx/lib/hidapi-0.7.0/windows/hidapi.sln (+29/-0)
mixxx/lib/hidapi-0.7.0/windows/hidapi.vcproj (+201/-0)
mixxx/lib/hidapi-0.7.0/windows/hidtest.vcproj (+196/-0)
mixxx/res/controllers/American-Audio-VMS4-scripts.js (+1/-1)
mixxx/res/controllers/EKS Otus.js (+95/-0)
mixxx/res/controllers/Eks Otus.cntrlr.xml (+13/-0)
mixxx/res/controllers/Stanton-SCS1d-scripts.js (+87/-104)
mixxx/res/controllers/Stanton-SCS3d-scripts.js (+23/-26)
mixxx/res/controllers/common-controller-scripts.js (+47/-14)
mixxx/res/mixxx.qrc (+1/-0)
mixxx/src/SConscript (+10/-10)
mixxx/src/controlbeat.cpp (+2/-1)
mixxx/src/controlbeat.h (+1/-2)
mixxx/src/controlgroupdelegate.cpp (+1/-1)
mixxx/src/controllers/controller-preset.cpp (+147/-0)
mixxx/src/controllers/controller.cpp (+153/-0)
mixxx/src/controllers/controller.h (+128/-0)
mixxx/src/controllers/controllerengine.cpp (+1132/-0)
mixxx/src/controllers/controllerengine.h (+136/-0)
mixxx/src/controllers/controllerenumerator.cpp (+28/-0)
mixxx/src/controllers/controllerenumerator.h (+36/-0)
mixxx/src/controllers/controllermanager.cpp (+315/-0)
mixxx/src/controllers/controllermanager.h (+86/-0)
mixxx/src/controllers/defs_controllers.h (+22/-0)
mixxx/src/controllers/dlgprefcontroller.cpp (+168/-0)
mixxx/src/controllers/dlgprefcontroller.h (+67/-0)
mixxx/src/controllers/dlgprefcontrollerdlg.ui (+140/-0)
mixxx/src/controllers/dlgprefnocontrollers.cpp (+25/-0)
mixxx/src/controllers/dlgprefnocontrollers.h (+33/-0)
mixxx/src/controllers/dlgprefnocontrollersdlg.ui (+46/-0)
mixxx/src/controllers/hidcontroller.cpp (+249/-0)
mixxx/src/controllers/hidcontroller.h (+75/-0)
mixxx/src/controllers/hidenumerator.cpp (+59/-0)
mixxx/src/controllers/hidenumerator.h (+31/-0)
mixxx/src/controllers/midi/hss1394controller.cpp (+211/-0)
mixxx/src/controllers/midi/hss1394controller.h (+66/-0)
mixxx/src/controllers/midi/hss1394enumerator.cpp (+60/-0)
mixxx/src/controllers/midi/hss1394enumerator.h (+31/-0)
mixxx/src/controllers/midi/midicontroller-preset.cpp (+468/-0)
mixxx/src/controllers/midi/midicontroller.cpp (+404/-0)
mixxx/src/controllers/midi/midicontroller.h (+91/-0)
mixxx/src/controllers/midi/midienumerator.cpp (+24/-0)
mixxx/src/controllers/midi/midienumerator.h (+37/-0)
mixxx/src/controllers/midi/midimessage.h (+89/-0)
mixxx/src/controllers/midi/midioutputhandler.cpp (+74/-0)
mixxx/src/controllers/midi/midioutputhandler.h (+51/-0)
mixxx/src/controllers/midi/portmidicontroller.cpp (+245/-0)
mixxx/src/controllers/midi/portmidicontroller.h (+67/-0)
mixxx/src/controllers/midi/portmidienumerator.cpp (+133/-0)
mixxx/src/controllers/midi/portmidienumerator.h (+32/-0)
mixxx/src/controllers/qtscript-bytearray/bytearrayclass.cpp (+284/-0)
mixxx/src/controllers/qtscript-bytearray/bytearrayclass.h (+91/-0)
mixxx/src/controllers/qtscript-bytearray/bytearrayprototype.cpp (+129/-0)
mixxx/src/controllers/qtscript-bytearray/bytearrayprototype.h (+76/-0)
mixxx/src/controllogpotmeter.cpp (+2/-1)
mixxx/src/controllogpotmeter.h (+1/-1)
mixxx/src/controlobject.cpp (+6/-8)
mixxx/src/controlobject.h (+4/-4)
mixxx/src/controlobjectthread.cpp (+2/-1)
mixxx/src/controlobjectthread.h (+3/-3)
mixxx/src/controlpotmeter.cpp (+2/-1)
mixxx/src/controlpotmeter.h (+1/-1)
mixxx/src/controlpushbutton.cpp (+4/-4)
mixxx/src/controlpushbutton.h (+2/-1)
mixxx/src/controlttrotary.cpp (+2/-1)
mixxx/src/controlttrotary.h (+2/-2)
mixxx/src/controlvaluedelegate.cpp (+1/-1)
mixxx/src/dlgmidilearning.cpp (+0/-210)
mixxx/src/dlgmidilearning.h (+0/-56)
mixxx/src/dlgmidilearning.ui (+0/-241)
mixxx/src/dlgpreferences.cpp (+160/-31)
mixxx/src/dlgpreferences.h (+28/-21)
mixxx/src/dlgprefmidibindings.cpp (+0/-508)
mixxx/src/dlgprefmidibindings.h (+0/-92)
mixxx/src/dlgprefmidibindingsdlg.ui (+0/-324)
mixxx/src/dlgprefnomidi.cpp (+0/-25)
mixxx/src/dlgprefnomidi.h (+0/-33)
mixxx/src/dlgprefnomididlg.ui (+0/-46)
mixxx/src/engine/ratecontrol.cpp (+2/-0)
mixxx/src/library/schemamanager.cpp (+2/-2)
mixxx/src/main.cpp (+2/-2)
mixxx/src/midi/hss1394enumerator.cpp (+0/-66)
mixxx/src/midi/hss1394enumerator.h (+0/-38)
mixxx/src/midi/midichanneldelegate.cpp (+0/-77)
mixxx/src/midi/midichanneldelegate.h (+0/-36)
mixxx/src/midi/mididevice.cpp (+0/-373)
mixxx/src/midi/mididevice.h (+0/-115)
mixxx/src/midi/mididevicedummy.h (+0/-42)
mixxx/src/midi/midideviceenumerator.cpp (+0/-28)
mixxx/src/midi/midideviceenumerator.h (+0/-38)
mixxx/src/midi/mididevicehss1394.cpp (+0/-233)
mixxx/src/midi/mididevicehss1394.h (+0/-66)
mixxx/src/midi/mididevicemanager.cpp (+0/-217)
mixxx/src/midi/mididevicemanager.h (+0/-54)
mixxx/src/midi/midideviceportmidi.cpp (+0/-325)
mixxx/src/midi/midideviceportmidi.h (+0/-60)
mixxx/src/midi/midiinputmapping.h (+0/-10)
mixxx/src/midi/midiinputmappingtablemodel.cpp (+0/-229)
mixxx/src/midi/midiinputmappingtablemodel.h (+0/-42)
mixxx/src/midi/midiledhandler.cpp (+0/-119)
mixxx/src/midi/midiledhandler.h (+0/-44)
mixxx/src/midi/midimapping.cpp (+0/-1178)
mixxx/src/midi/midimapping.h (+0/-175)
mixxx/src/midi/midimessage.cpp (+0/-111)
mixxx/src/midi/midimessage.h (+0/-114)
mixxx/src/midi/midinodelegate.cpp (+0/-75)
mixxx/src/midi/midinodelegate.h (+0/-36)
mixxx/src/midi/midioptiondelegate.cpp (+0/-158)
mixxx/src/midi/midioptiondelegate.h (+0/-39)
mixxx/src/midi/midioutputmapping.h (+0/-10)
mixxx/src/midi/midioutputmappingtablemodel.cpp (+0/-263)
mixxx/src/midi/midioutputmappingtablemodel.h (+0/-44)
mixxx/src/midi/midiscriptengine.cpp (+0/-1342)
mixxx/src/midi/midiscriptengine.h (+0/-145)
mixxx/src/midi/midistatusdelegate.cpp (+0/-121)
mixxx/src/midi/midistatusdelegate.h (+0/-39)
mixxx/src/midi/portmidienumerator.cpp (+0/-135)
mixxx/src/midi/portmidienumerator.h (+0/-37)
mixxx/src/mixxx.cpp (+27/-25)
mixxx/src/mixxx.h (+2/-3)
mixxx/src/mixxx.rc (+2/-2)
mixxx/src/mixxxkeyboard.cpp (+2/-2)
mixxx/src/recording/recordingmanager.cpp (+1/-0)
mixxx/src/skin/propertybinder.cpp (+2/-0)
mixxx/src/softtakeover.cpp (+2/-2)
mixxx/src/softtakeover.h (+1/-1)
mixxx/src/test/controllerengine_test.cpp (+104/-25)
mixxx/src/widget/wwidget.cpp (+0/-20)
mixxx/src/widget/wwidget.h (+0/-2)
mixxx/src/xmlparse.cpp (+23/-0)
mixxx/src/xmlparse.h (+2/-0)
To merge this branch: bzr merge lp://qastaging/~mixxxdevelopers/mixxx/features_controllerAbstraction
Reviewer Review Type Date Requested Status
RJ Skerry-Ryan Needs Fixing
Review via email: mp+98121@code.qastaging.launchpad.net

This proposal has been superseded by a proposal from 2012-04-07.

Commit message

Abstracts the controller subsystem to support multiple protocols. MIDI subsystem partially rewritten, directories, classes and threads reorganized. Adds full HID controller support. Removes MIDI mapping GUI for now.

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

Maybe I missed the discussion on this but while I agree that the GUI mapping support totally sucks do we really want to remove it without replacing it?

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

For 1.11 I think we're just going to remove it. The general reasoning is
that since we haven't really had anyone complaining about how hard it is to
use like about 2 years of it being there.. the only conclusion must be that
close to nobody uses it.

Code-wise it was very complicated too and really screwed up the MIDI
mapping implementation since they were deeply intertwined. I'd rather nuke
it in 1.11 and come up with a really nice one for 1.12 or create an
external mapping program.

On Sun, Mar 18, 2012 at 9:26 PM, Bill Good <email address hidden> wrote:

> Maybe I missed the discussion on this but while I agree that the GUI
> mapping support totally sucks do we really want to remove it without
> replacing it?
> --
>
> https://code.launchpad.net/~mixxxdevelopers/mixxx/features_controllerAbstraction/+merge/98121
> You proposed lp:~mixxxdevelopers/mixxx/features_controllerAbstraction for
> merging.
>

Revision history for this message
Sean M. Pappalardo (pegasus-renegadetech) wrote :

We could add back the MIDI mapping wizard if you like, since there's already a message signal and a learning flag in place in MidiController. MC just needs a slot to get data from the wizard, then the wizard would need to be adjusted to work with these signals/slots. I'll check into this further.

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :
Download full text (3.9 KiB)

Hey Sean,

I realize you haven't put the finishing touches on the branch yet. I'm sorry in advance because this review is going to seem a little brutal but I'm convinced that we need to do things right. The main problem I saw with the MIDI subsystem in 1.10 is that everything was totally commingled. This made it impossible to write unit tests for a given class because we had swiss-army-knife classes that did everything. We need to move away from this.

I want to get you this feedback as soon as possible, so here it is. I may have more comments to share later.

* Please make sure to remove commented code referring to non-existing stuff (e.g. all commented lines you left in build/depends.py that refer to old files that don't exist anymore)

* Make sure to delete "res/controllers/Stanton SCS.1m VUMETERS ONLY.xml"

* Please delete src/controllers/OLDmidi soon because it makes reviewing your branch hard (the diff is gigantic).

* In defs_controllers.h, make helper functions instead of these macros. (DEFAULT_DEVICE_PRESET, DEFAULT_MIDI_DEVICE_PRESET in particular. Ideally PRESETS_PATH and LPRESETS_PATH as well).

* Please add "virtual" to every destructor declaration.

* It's good that the old MidiMapping class died because it was a mutable-shared-state-logic-monster. That said, storing the mappings in the controller is almost as bad.
   - Let's pull all mappings out into a Mapping/MidiMapping class. This class should be plain-old-data, not a QObject (e.g. no signals/slots) and no methods except the minimum needed for Controller to look up the script files, MidiController to look up a mapped control in receive() and to look up output mappings where it creates the MidiOutputHandlers.

* Take all serialization/deserialization code and put it into a MappingParser/MidiMappingParser helper class which creates a Mapping/MidiMapping class from a given path.

* Delete loadPreset / savePreset / buildDomElement methods in Controller/MidiController .. replace them with a setMapping() command. A controller that doesn't have a mapping yet can be considered invalid.

* Controllers shouldn't be concerned with saving a preset. Instead that should be the controller preferences dialog or the ControllerManager's job to deserialize the mapping and call Controller::setMapping().

* Need to remove all methods that deal with a char*/length data buffer e.g. Controller::send, Controller::receivePointer. Instead we should be using QByteArray for everything.

* Remove length argument from Controller::sendBa since a QByteArray knows its own length. Also, rename sendBa to send(). Also make the argument a const QByteArray.

* I'd prefer we get rid of the Controller::send(QList<int>) method and instead require people to use QByteArrays but I'm not sure if this is easy from scripts so maybe we can let it be. Please change the implementation of Controller::send(QList<int>, int) to build a QByteArray and call send(QByteArray).

* In ControllerManager, please remove the m_pPMEnumerator, m_pHSSEnumerator, m_pHIDEnumerator, and m_pOSCEnumerator declarations. Instead use a QList of ControllerEnumerator* objects. Add an "addControllerEnumerator()" method to ControllerManager, an...

Read more...

review: Needs Fixing
Revision history for this message
Sean M. Pappalardo (pegasus-renegadetech) wrote :

> * Please make sure to remove commented code referring to non-existing stuff
> * Make sure to delete "res/controllers/Stanton SCS.1m VUMETERS ONLY.xml"
> * Please delete src/controllers/OLDmidi soon because it makes reviewing your

These are among the reasons why I didn't propose a merge yet, silly. :)

> * In defs_controllers.h, make helper functions instead of these macros.

What benefit would that give? The macros are straightforward and fast.

> * Please add "virtual" to every destructor declaration.

As a matter of course? What will that do? I only do it to destructors that will be reimplemented.

> shared-state-logic-monster. That said, storing the mappings in the controller
> is almost as bad.

I do this because I view a Controller as a device, with all properties particular to that device (e.g. a mapping) contained in the one object. Then due to the time-sensitive nature of MIDI processing, I imagine local object data is faster to access.

> * Take all serialization/deserialization code and put it into a
> MappingParser/MidiMappingParser helper class which creates a
> Mapping/MidiMapping class from a given path.

That sounds like overkill. If we do in fact make a MidiMapping class, shouldn't the same class that holds the data be responsible for all operations on that data?

> * Need to remove all methods that deal with a char*/length data buffer e.g.
> Controller::send, Controller::receivePointer. Instead we should be using
> QByteArray for everything.

Not all of them can be removed without duplicating code or complicating the classes, since the device APIs send and expect data this way. If we try, know that interfacing raw bytes between JS and C++ is a very delicate issue. I've had numerous problems with bytes getting mangled in the past.
Plus I imagine primitive data types to be slightly faster. Here again, what would be the benefit of switching to QByteArrays?

> * I'd prefer we get rid of the Controller::send(QList<int>) method and instead
> require people to use QByteArrays

We can't. This is how QtScript passes data byte arrays to C++.

> * In ControllerManager, please remove the m_pPMEnumerator, m_pHSSEnumerator,
> m_pHIDEnumerator, and m_pOSCEnumerator declarations.

Thanks for the suggested methods. This was bothering me too but I couldn't think of a neat way to fix it.

> * midi-mappings-scripts.js You're changing the names of a lot of common script
> stuff. Won't this break MIDI-scripts in the wild?

Yes, but the only things that will be incompatible are MidiButtonState and MidiLedState. A README telling to search-n-replace will fix them right up. I left backwards-compatible calls for everything else.

Revision history for this message
Owen Williams (ywwg) wrote :

We should think long and hard before breaking people's scripts, even if a simple search-and-replace will fix it. I'd prefer to leave scripts stable and only limit breakage to major releases (2.0, etc). I'm not super-familiar with this branch, but is this breakage necessary?

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :
Download full text (5.5 KiB)

On Mon, Mar 19, 2012 at 4:14 PM, Sean M. Pappalardo
<email address hidden>wrote:

> > * Please make sure to remove commented code referring to non-existing
> stuff
> > * Make sure to delete "res/controllers/Stanton SCS.1m VUMETERS ONLY.xml"
> > * Please delete src/controllers/OLDmidi soon because it makes reviewing
> your
>
> These are among the reasons why I didn't propose a merge yet, silly. :)
>
> > * In defs_controllers.h, make helper functions instead of these macros.
>
> What benefit would that give? The macros are straightforward and fast.
>

Macros should only be used for constants. They're no faster than an inline
function. These particular macros refer to member variables of a class and
have logic in them. This obscures the logic within the class they are used
in because it is hidden behind what looks like a constant. If they have
member variables then they're specific to a class so why not make them a
private inline helper function of that class?

>
> > * Please add "virtual" to every destructor declaration.
>
> As a matter of course? What will that do? I only do it to destructors that
> will be reimplemented.
>
>
It's just something that every class should have. It should be as automatic
as making your member variables private. Some day in the future someone
will subclass your class -- guaranteed. Be nice to them -- it might even be
your future self. :)

> > shared-state-logic-monster. That said, storing the mappings in the
> controller
> > is almost as bad.
>
> I do this because I view a Controller as a device, with all properties
> particular to that device (e.g. a mapping) contained in the one object.
> Then due to the time-sensitive nature of MIDI processing, I imagine local
> object data is faster to access.
>
>
It's fine for the controller to have a mapping. That mapping should be
encapsulated into one class so you can pass them around and vary the
implementation of the mapping independent of the class that consumes the
mapping (the Controller).

Accessing a member variable versus the member variable of another class is
possibly the difference in 1 or two assembly instructions -- if any
difference. If you care about this in the name of speed then I'm surprised
you use so many virtual functions (they are about 2x slower than a regular
function call). This sort of difference is totally meaningless from a Mixxx
performance perspective. We're talking picoseconds here!

Don't let tens or hundreds of assembly instructions get in the way of
writing good code. For the long-term health of the project it's worth it to
structure the project in small, bite-sized and testable classes. This is
extra work, I know.

> > * Take all serialization/deserialization code and put it into a
> > MappingParser/MidiMappingParser helper class which creates a
> > Mapping/MidiMapping class from a given path.
>
> That sounds like overkill. If we do in fact make a MidiMapping class,
> shouldn't the same class that holds the data be responsible for all
> operations on that data?
>

The mapping parsing / serializing code is long enough to warrant living in
its own utility class. It is long and obscures the purpose of whatever
class it lives in (origin...

Read more...

Revision history for this message
Sean M. Pappalardo (pegasus-renegadetech) wrote :

> Macros should only be used for constants.

My bad, I forgot there were member variables in two of them. Don't know what I was thinking when I did that.

> difference. If you care about this in the name of speed then I'm surprised
> you use so many virtual functions (they are about 2x slower than a regular
> function call).

:O I had no idea! Is that 2x slowdown a matter of picoseconds too?

> The mapping parsing / serializing code is long enough to warrant living in
> its own utility class. It is long and obscures the purpose of whatever
> class it lives in (originally MidiMapping, now *Controller).

What bothers me about separating it is that there is no generic ControllerMapping class (at least not yet,) so MidiMappings are specific to MIDI controllers, so why not make them an integral part? I see your point though and will make the change.

> 1.10. Can we keep the ButtonState and LedState as they are for MIDI and
> mark them deprecated?

Actually, leaving them without the "Midi" prefix should be fine, since non-MIDI controllers will need to set the values differently anyway.

Revision history for this message
Sean M. Pappalardo (pegasus-renegadetech) wrote :

LOL, I removed the OLDmidi directory and the diff got bigger. (Not surprised.)

RJ, while I work on the rest, I need you to take a look at ControllerEngine::connectControl() and figure out why using COTs breaks automatic reactions. They work fine in trunk so I have no idea.

Revision history for this message
Sean M. Pappalardo (pegasus-renegadetech) wrote :

Hello again. Looking at your class-separation requests more closely now, I still have reservations:

> - Let's pull all mappings out into a Mapping/MidiMapping class. This class
> should be plain-old-data, not a QObject (e.g. no signals/slots) and no methods

I'm sorry, I can't see the benefit of doing that. It would just add complexity and make it harder for *Controller to be expanded in the future such as when the GUI signals it to add/delete/change mappings. (Besides, a preset is just two QLists. Specific *Controllers add two QHashes for mappings.)

> * Take all serialization/deserialization code and put it into a
> MappingParser/MidiMappingParser helper class

Here too, moving those functions to another class would add needless complexity because they have to access data that's specific to a Controller. I understand the desire to have classes not be too long, but don't let that get in the way of logical design. In this case, everything that's in *Controller is specific to that type of device. (Yes, that includes the parsing code, since it's specific to the mapping storage format, which is specific to the device type.) Trying to separate it across multiple classes would cause us to have shared-state logic monsters again and make it much more difficult to follow for those new to the code. Since it sounds like you're interested in visual separation, I have moved the functions that handle XML into separate .cpp files and have simply #included these in the main *Controller ones.

> * Controllers shouldn't be concerned with saving a preset. Instead that should
> be the controller preferences dialog or the ControllerManager's job

The ControllerManager _is_ in charge of saving presets. The Controllers just contain the code to do so, because it's specific to each Controller type (as stated above,) and the Manager isn't concerned with those details (or it would be micro-managing.)

In short, there's nothing else that can be factored out.

If your concerns are motivated by unit-testing issues, why can't we just write separate tests for different aspects of a class?

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :
Download full text (3.4 KiB)

On Apr 7, 2012 7:38 AM, "Sean M. Pappalardo" <email address hidden> wrote:
>
> Hello again. Looking at your class-separation requests more closely now,
I still have reservations:
>
> > - Let's pull all mappings out into a Mapping/MidiMapping class. This
class
> > should be plain-old-data, not a QObject (e.g. no signals/slots) and no
methods
>
> I'm sorry, I can't see the benefit of doing that. It would just add
complexity and make it harder for *Controller to be expanded in the future
such as when the GUI signals it to add/delete/change mappings. (Besides, a
preset is just two QLists. Specific *Controllers add two QHashes for
mappings.)

The benefit is encapsulation of the mapping implementation.

Add/delete/change of a mapping from the GUI is the reason the old midi
system is so terrible. The only way to load a mapping going forward will be
to call Controller::loadMapping(ControllerMapping).

>
> > * Take all serialization/deserialization code and put it into a
> > MappingParser/MidiMappingParser helper class
>
> Here too, moving those functions to another class would add needless
complexity because they have to access data that's specific to a
Controller. I understand the desire to have classes not be too long, but
don't let that get in the way of logical design. In this case, everything
that's in *Controller is specific to that type of device. (Yes, that
includes the parsing code, since it's specific to the mapping storage
format, which is specific to the device type.) Trying to separate it across
multiple classes would cause us to have shared-state logic monsters again
and make it much more difficult to follow for those new to the code. Since
it sounds like you're interested in visual separation, I have moved the
functions that handle XML into separate .cpp files and have simply
#included these in the main *Controller ones.

Putting this in a separate helper will allow us to test it and it will
simplify the ControllerMapping class considerably.

>
> > * Controllers shouldn't be concerned with saving a preset. Instead that
should
> > be the controller preferences dialog or the ControllerManager's job
>
> The ControllerManager _is_ in charge of saving presets. The Controllers
just contain the code to do so, because it's specific to each Controller
type (as stated above,) and the Manager isn't concerned with those details
(or it would be micro-managi

I think saving presets should be owned by the controller preferences dialog
and not even be part of the controller manager actually.

>
> In short, there's nothing else that can be factored out.
>
> If your concerns are motivated by unit-testing issues, why can't we just
write separate tests for different aspects of a class?

Well the general reason why this is is that you can't isolate the logic you
aim to test when it's all mixed together in one class.

I feel bad coming down hard but these issues are non-negotiable. In the
past I haven't held the MIDI subsystem to as high a standard as say the
engine but now that you are rewriting it I'd like to change that. "It
works" is not good enough for infrastructure code (which this is going to
be more than ever as we add more controller types) so...

Read more...

2818. By Sean M. Pappalardo

Improvements to soft-takeover algorithm. It works really well now.

2819. By Sean M. Pappalardo

WIP: class-ifying the ControllerPresets and ControllerPresetFileHandlers. Currently broken, committing so RJ can take a look.

2820. By RJ Skerry-Ryan

* Add HidControllerPreset and HidControllerPresetFileHandler
  (necessary to keep ControllerPreset and ControllerPresetFileHandler
  abstract)

* Many fixes here and there to get things building.

* Add ControllerPresetVisitor, a visitor to get a Controller subclass
  the real type of the preset being loaded to it.

2821. By RJ Skerry-Ryan

Check for null handlers and presets.

2822. By RJ Skerry-Ryan

Minor errors, use QSet instead of QList for faster contains() checking.

2823. By RJ Skerry-Ryan

Constify a lot of stuff. Switch to having the controller be in charge of saving the preset because it knows the true type of the preset. If I didn't do this then I would have had to make ControllerPresetFileHandler a ControllerPresetVisitor as well, which isn't worth the extra lines of code. Fix some broken/unfinished code so the branch builds.

2824. By RJ Skerry-Ryan

Cleanup lint / style fixes in ControllerManager.

2825. By RJ Skerry-Ryan

error messages for preset mismatches.

2826. By RJ Skerry-Ryan

Tons of cleanups across the whole controllers/ hierarchy.

2827. By RJ Skerry-Ryan

Merging from lp:mixxx

2828. By Sean M. Pappalardo

- Removed all old MIDI code from dlgpreferences
- Fixed compilation with HID enabled after RJ's codefest.
- Replaced the dialog's ability to signal a controller preset load
- Removed the ConfigObject creation in ControllerEngine by passing it to Controller which passes the path the CE needs.
- ControllerManager and ControllerEngine now look for presets and script files in both res/ and the user directory
- Made MidiController::close() destroy the outputHandlers and set the *MidiControllers to call it within their close() functions.
- Added directory copy from midi/ to controllers/ in upgrade.cpp. Also improved the version number processing.

2829. By Sean M. Pappalardo

- Removed more old commented MIDI dialog code
- Cleaned up MixxxControl and added more properties. Perhaps it will become the center of Control 2.0 eventually?
- Converted the Controller subsystem to use MixxxControls instead of ConfigKeys. It's a bit cleaner.
- WIP: Trying to set up a DlgMappableController as a subclass of DlgController but it's showing the UI from the superclass. Help!
- WIP: DlgControllerLearning. I just comitted it so RJ can build to take a look at the above issue.

2830. By RJ Skerry-Ryan

Add IOKit and CoreFoundation frameworks. Fixes build on OS X

2831. By Sean M. Pappalardo

Fixed DlgMappableController selection and display. I can't get the table to expand to full window width so I'll need help with that.

2832. By Sean M. Pappalardo

- DlgMappableController successfully subclasses DlgController now
- Controller learning (MIDI) works now, though I can't test for sure since I won't be near a MIDI controller for weeks. NEED SOMEONE TO TEST PLEASE!!
- Made control descriptions easier to read, added count
- Sorted control descriptions by group
- Got number of decks and samplers from the global COs
- Disabled a bunch of not-yet-implemented stuff in the mapping pane.

2833. By Sean M. Pappalardo

Neatened up MIDI message display in learning dialog and prevented controls from affecting Mixxx during learning.

2834. By Sean M. Pappalardo

Made the Clear All button work.

2835. By RJ Skerry-Ryan

Get rid of fputs in upgrade.cpp

2836. By RJ Skerry-Ryan

Mass reformat tabs in SConscript to spaces. Remove all license blocks from src/controllers. Fix lint here and there. Remove unused code from MixxxControl.

2837. By RJ Skerry-Ryan

Rewrite SoftTakeover to use ControlObjects instead of MixxxControl.

2838. By RJ Skerry-Ryan

Move SoftTakeover to src/controllers/. Add more virtual destructors and fix style issues here and there.

2839. By RJ Skerry-Ryan

Remove more licenses. Fix more lint.

2840. By RJ Skerry-Ryan

Move HID code to src/controllers/hid.

2841. By RJ Skerry-Ryan

Move MixxxControl to src/controllers.

2842. By RJ Skerry-Ryan

Get rid of passing ControllerProcessor timerEvent()'s directly in favor of just calling a Controller::poll() method when the controller needs to poll (if it has polling enabled).

2843. By RJ Skerry-Ryan

Delete ControllerProcessor since it was just a wrapper around a QTimer essentially.

2844. By RJ Skerry-Ryan

Prevent changing visibility for a few methods. Mass re-format some class definitions to conform to mixxx indentation style.

2845. By RJ Skerry-Ryan

Comments, formatting.

2846. By RJ Skerry-Ryan

Remove redundant/unused code here and there.

2847. By RJ Skerry-Ryan

Parent DeviceChannelListener to its HSS1394Controller.

2848. By RJ Skerry-Ryan

* Remove polling declaration from ControllerEnumerator and put it in
  the Controllers themselves.

* Make all variables of Controller private and make sub-classes access
  via accessors.

2849. By RJ Skerry-Ryan

Remove dups option from MidiOutputHandler since it wasn't used anywhere.

2850. By RJ Skerry-Ryan

Add locking to protect m_controllers list in ControllerManager. Other misc cleanups.

2851. By RJ Skerry-Ryan

Make DlgPrefController vars private.

2852. By RJ Skerry-Ryan

Make DlgPrefController not call open() or close() on controllers anymore. Switch HidReader to use QAtomicInt instead of bool flag.

2853. By RJ Skerry-Ryan

Oops. Fix a bug I wrote in preset loading.

2854. By RJ Skerry-Ryan

Sean -- please take a look at the comment I left. Not sure what the desired behavior is here.

2855. By Sean M. Pappalardo

loadPreset takes a filename, not device name

2856. By RJ Skerry-Ryan

Clear pointer on delete.

2857. By Sean M. Pappalardo

Merging from trunk

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
The diff is not available at this time. You can reload the page or download it.

Subscribers

People subscribed via source and target branches