Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QML: Add support for selecting/loading effects #4000

Merged
merged 26 commits into from
Jun 22, 2021

Conversation

Holzhaus
Copy link
Member

Based on #3992.

@Swiftb0y
Copy link
Member

Please Rebase.

Also PR nr 4000. Yeah 🎉

@Holzhaus
Copy link
Member Author

Holzhaus commented Jun 15, 2021

Caveat: The comboboxes currently don't have any signal connections to the actual effect slot. This means changing the effects from the controller or via COs won't update the combobox atm.

Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really can't comment on any C++ changes. Though the current approach seems a bit clunky to me.

res/skins/QMLDemo/EffectUnit.qml Outdated Show resolved Hide resolved
class QmlVisibleEffectsModel : public QAbstractListModel {
Q_OBJECT
public:
enum Roles {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enum class? not sure though if that works with Q_ENUM

Copy link
Member Author

@Holzhaus Holzhaus Jun 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works, but it's kind of clunky because of all the casting between int and the enum value. Since the enum part of the class body and each member has a "Role" suffix, I think it's okay like this.

@uklotzde what do you think?

model: Mixxx.EffectsManager.visibleEffectsModel
onActivated: {
console.warn(1, root.unitNumber, effect.effectNumber, model.get(index).effectId);
Mixxx.EffectsManager.loadEffect(1, root.unitNumber, effect.effectNumber, model.get(index).effectId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I like this... Though I don't really have anything better to propose...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question is how do we receive changes. I checked the controls and didn't see any COs that indicate the currently loaded effect. Therefore I think we need to add a QmlEffectChainSlotProxy that can emit signals when the effect is changed. If we do that, we can move the load method there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Binding to (EffectRack1_EffectUnitN_EffectM,loaded) might work. It should emit a "trigger" signal even if the value didn't change. But in the long term, we do need QmlEffectChainSlotProxy anyways so we can configure the parameters and so forth. We might even consider trying to remove the GUI changes from #2618 and redo that part based on QML.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we actually need it for parameter configuration except the names.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well we don't really need it, but I find the current way its implemented with COs very hacky and would like to get rid of it in the longterm actually..

@Swiftb0y
Copy link
Member

Clicking outside the Combobox popup doesn't close it for some reason. I need to click on another interactive element such as a Button or Knob. It would also be great if the combobox was editable and you could just search for the effect you wanted in the model, but thats polish to be done later.

@Swiftb0y
Copy link
Member

I'm questioning whether this is a good approach. The overengineering of the effect system makes it really hard to judge properly.
I personally don't like the amount of "getters on globals" (such as Mixxx.EffectsManager.getEffectSlot) for example.

I'm ok with merging it as it for the sake of progress, but I don't want to have to commit to this API in the longterm.

@Holzhaus
Copy link
Member Author

I agree, but on the other hand I don't know if it's possible to expose stuff like that with making EffectsManager a singleton which I dislike even more.

Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not super happy with the QML but its fine as a short term solution. I'd prefer if someone with more C++ experience would take a look at that though before merging.

@Holzhaus
Copy link
Member Author

I also added initial support for expandable effect units. Don't pay too much attention to that, it's not that useful yet because there is no support for effect parameter names, linking or other fancy stuff yet.

I'll probably have to refactor it later on by implementing a QmlEffectParametersModel that is used by a ListView. It'll take care of that in a separate PR.

@Holzhaus
Copy link
Member Author

Holzhaus commented Jun 21, 2021

Nevermind, switched to the ListView approach in this PR.

@Holzhaus Holzhaus requested a review from Swiftb0y June 21, 2021 16:14
Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size of the line indicator seems too big.
image

res/skins/QMLDemo/EffectRow.qml Show resolved Hide resolved
res/skins/QMLDemo/EffectSlot.qml Outdated Show resolved Hide resolved
property int unitNumber // required
property int effectNumber // required
property bool expanded: false
readonly property string group: slot.group
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
readonly property string group: slot.group
property alias group: slot.group

I assume this doesn't work?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't try, maybe the readonly flag from the slot property is also applying to the alias. I can check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, doesn't work. Maybe because the order of property initializiation is not defined or something:

warning [Main] file:///home/jan/Projects/mixxx/res/skins/QMLDemo/main.qml:120:9: Type EffectRow unavailable
             EffectRow {
             ^
warning [Main] file:///home/jan/Projects/mixxx/res/skins/QMLDemo/EffectRow.qml:14:9: Type Skin.EffectUnit unavailable
             Skin.EffectUnit {
             ^
warning [Main] file:///home/jan/Projects/mixxx/res/skins/QMLDemo/EffectUnit.qml:24:9: Type EffectSlot unavailable
             EffectSlot {
             ^
warning [Main] file:///home/jan/Projects/mixxx/res/skins/QMLDemo/EffectSlot.qml:13:27: Invalid alias reference. Unable to find id "slot"
         property alias group: slot.group
                               ^
warning [Main] Skin "QMLDemo" failed to load!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mhmm thats strange. I guess I'm misinterpreting the Qt docs section https://doc.qt.io/qt-5/qtqml-syntax-objectattributes.html#considerations-for-property-aliases

res/skins/QMLDemo/EffectSlot.qml Outdated Show resolved Hide resolved
res/skins/QMLDemo/EffectSlot.qml Show resolved Hide resolved
res/skins/QMLDemo/EffectSlot.qml Outdated Show resolved Hide resolved
@@ -1,75 +1,109 @@
import "." as Skin
import Mixxx 0.1 as Mixxx
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import "Theme"

Item {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if you think the effort is worth it, but you could add the expanded controls from latenight as well:
image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is already quite big. Someone can take care of that separately I think. There's also other stuff missing, like the link type, or configuring the knob arc start from the parameter, etc.

src/skin/qml/qmleffectmanifestparametersmodel.cpp Outdated Show resolved Hide resolved
Comment on lines +50 to +52
if (parent.isValid()) {
return 0;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (parent.isValid()) {
return 0;
}
if (!parent.isValid()) {
return 0;
}

not sure how the QModelIndex API is used, but returning early when the parent is valid seems strange.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This model is a list. This means it has N rows. If parent is valid, this means that we're not requesting the rowCount for the whole list, but for an individual item. If this was a tree model (like the library sidebar), then each item might also have children. This is not the case here. Therefore, we always return zero, because no item has children.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand now. Thanks for the explanation. I guess I should read the Qt docs first without asking questions in code review.

@Holzhaus Holzhaus requested a review from Swiftb0y June 21, 2021 19:47
Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Unfortunately there are still two blocking issues IMO.

  1. The effectUnit desperately needs a DryWet knob, otherwise the unit stays inaudible when mixxx started completely dry.
  2. The buttons for the parameters of a effect don't actually work atm. You can most easily test this using the Tremolo Effect and playing with the Quantize and Triplet buttons.

res/skins/QMLDemo/EffectSlot.qml Show resolved Hide resolved
@Holzhaus
Copy link
Member Author

Thanks. Unfortunately there are still two blocking issues IMO.

  1. The effectUnit desperately needs a DryWet knob, otherwise the unit stays inaudible when mixxx started completely dry.

I don't consider this a blocker, but I added it. Only visible when expanded though.

  1. The buttons for the parameters of a effect don't actually work atm. You can most easily test this using the Tremolo Effect and playing with the Quantize and Triplet buttons.

I checked, and some buttons did work, some did not, because our effect CO infrastructure is badly designed IMHO. I tried to mitigate this by adding a way to retrieve the parameter control key from the model.

@Holzhaus Holzhaus requested a review from Swiftb0y June 22, 2021 11:09
Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked, and some buttons did work, some did not, because our effect CO infrastructure is badly designed IMHO. I tried to mitigate this by adding a way to retrieve the parameter control key from the model.

Thats very strange I'll guess we should take care of it in conjunction with #2618.

LGTM. I guess no one else is interested in reviewing this so I'm just going to merge now.

@Swiftb0y Swiftb0y merged commit 5c20663 into mixxxdj:main Jun 22, 2021
@ywwg
Copy link
Member

ywwg commented Jun 28, 2021

This merge seems to have made mixxx unbuildable at HEAD for me:

/usr/bin/ld: libmixxx-lib.a(mocs_compilation.cpp.o): in function `mixxx::skin::qml::QmlEffectsManagerProxy::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)':
mocs_compilation.cpp:(.text+0x9a4): undefined reference to `mixxx::skin::qml::QmlEffectsManagerProxy::getEffectSlot(int, int, int) const'
/usr/bin/ld: libmixxx-lib.a(mocs_compilation.cpp.o): in function `mixxx::skin::qml::QmlVisibleEffectsModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)':
mocs_compilation.cpp:(.text+0xa8d): undefined reference to `mixxx::skin::qml::QmlVisibleEffectsModel::get(int) const'
/usr/bin/ld: libmixxx-lib.a(mocs_compilation.cpp.o): in function `mixxx::skin::qml::QmlEffectManifestParametersModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)':
mocs_compilation.cpp:(.text+0xb6f): undefined reference to `mixxx::skin::qml::QmlEffectManifestParametersModel::get(int) const'
/usr/bin/ld: libmixxx-lib.a(mocs_compilation.cpp.o): in function `mixxx::skin::qml::QmlEffectSlotProxy::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)':
mocs_compilation.cpp:(.text+0xe7a): undefined reference to `mixxx::skin::qml::QmlEffectSlotProxy::getEffectId() const'
/usr/bin/ld: mocs_compilation.cpp:(.text+0xeca): undefined reference to `mixxx::skin::qml::QmlEffectSlotProxy::getGroup() const'
/usr/bin/ld: mocs_compilation.cpp:(.text+0xed1): undefined reference to `mixxx::skin::qml::QmlEffectSlotProxy::getNumber() const'
/usr/bin/ld: mocs_compilation.cpp:(.text+0xeea): undefined reference to `mixxx::skin::qml::QmlEffectSlotProxy::getChainSlotGroup() const'
/usr/bin/ld: mocs_compilation.cpp:(.text+0xef1): undefined reference to `mixxx::skin::qml::QmlEffectSlotProxy::getChainSlotNumber() const'
/usr/bin/ld: mocs_compilation.cpp:(.text+0xf0a): undefined reference to `mixxx::skin::qml::QmlEffectSlotProxy::getRackGroup() const'
/usr/bin/ld: mocs_compilation.cpp:(.text+0xf19): undefined reference to `mixxx::skin::qml::QmlEffectSlotProxy::getRackNumber() const'
/usr/bin/ld: mocs_compilation.cpp:(.text+0xf29): undefined reference to `mixxx::skin::qml::QmlEffectSlotProxy::getParametersModel() const'

Bisecting identifies the first bad commit as: 8cab623

At first glance I have no idea why.

@ywwg
Copy link
Member

ywwg commented Jun 28, 2021

Cleaning out cbuild seems to fix it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants