Skip to content

Commit

Permalink
feat: add UI for stem on QML
Browse files Browse the repository at this point in the history
Switch the equalizer mixer to stem control if the deck is loaded with a
stem file
  • Loading branch information
acolombier committed Jul 14, 2024
1 parent d14d0db commit 36af073
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 27 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3463,6 +3463,12 @@ if (STEM)
src/waveform/renderers/allshader/waveformrendererstem.cpp
)
endif()
if(QML)
target_compile_definitions(mixxx-qml-lib PUBLIC __STEM__)
target_sources(mixxx-qml-lib PRIVATE
src/qml/qmlstemsmodel.cpp
)
endif()
endif()

# Test Suite
Expand Down
119 changes: 93 additions & 26 deletions res/qml/EqColumn.qml
Original file line number Diff line number Diff line change
@@ -1,44 +1,111 @@
import "." as Skin
import QtQuick 2.12
import QtQuick.Shapes 1.12
import QtQuick.Layouts
import Mixxx 1.0 as Mixxx
import "Theme"

Column {
id: root

required property string group
property var player: Mixxx.PlayerManager.getPlayer(root.group)

spacing: 4
Mixxx.ControlProxy {
id: stemCountControl

Skin.EqKnob {
statusKey: "button_parameter3"
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter3"
knob.color: Theme.eqHighColor
group: root.group
key: "stem_count"
}

Skin.EqKnob {
statusKey: "button_parameter2"
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter2"
knob.color: Theme.eqMidColor
}
Row {
Column {
id: stem
spacing: 4
visible: opacity != 0
Repeater {
model: root.player.stemsModel

Skin.EqKnob {
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter1"
statusKey: "button_parameter1"
knob.color: Theme.eqLowColor
}
Row {
id: stem
required property int index
required property string label
required property color color

Skin.StemKnob {
group: root.group
index: stem.index
label: stem.label
stemColor: stem.color
}
}
}
}
Column {
id: eq
spacing: 4
width: 10
visible: opacity != 0
Skin.EqKnob {
statusKey: "button_parameter3"
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter3"
knob.color: Theme.eqHighColor
}

Skin.EqKnob {
statusKey: "button_parameter2"
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter2"
knob.color: Theme.eqMidColor
}

Skin.EqKnob {
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter1"
statusKey: "button_parameter1"
knob.color: Theme.eqLowColor
}

Skin.EqKnob {
knob.group: "[QuickEffectRack1_" + root.group + "]"
knob.key: "super1"
statusGroup: "[QuickEffectRack1_" + root.group + "_Effect1]"
statusKey: "enabled"
knob.arcStyle: ShapePath.DashLine
knob.arcStylePattern: [2, 2]
knob.color: Theme.eqFxColor
}
}
states: [
State {
name: "eq"
when: stemCountControl.value == 0
PropertyChanges { target: stem; opacity: 0; width: 0}
},
State {
name: "stem"
when: stemCountControl.value != 0
PropertyChanges { target: eq; opacity: 0; width: 0 }
}
]

Skin.EqKnob {
knob.group: "[QuickEffectRack1_" + root.group + "]"
knob.key: "super1"
statusGroup: "[QuickEffectRack1_" + root.group + "_Effect1]"
statusKey: "enabled"
knob.arcStyle: ShapePath.DashLine
knob.arcStylePattern: [2, 2]
knob.color: Theme.eqFxColor
transitions: [
Transition {
from: "eq"
to: "stem"
ParallelAnimation {
PropertyAnimation { targets: [eq, stem]; properties: "opacity,width"; duration: 1000}
}
},
Transition {
from: "stem"
to: "eq"
ParallelAnimation {
PropertyAnimation { targets: [eq, stem]; properties: "opacity,width"; duration: 1000}
}
}
]
}

Skin.OrientationToggleButton {
Expand Down
1 change: 1 addition & 0 deletions res/qml/Mixer.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "." as Skin
import Mixxx 1.0 as Mixxx
import QtQuick 2.12

Item {
Expand Down
67 changes: 67 additions & 0 deletions res/qml/StemKnob.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import "." as Skin
import Mixxx 1.0 as Mixxx
import QtQuick 2.12
import "Theme"

Rectangle {
id: root

property alias knob: knob

required property string group
required property string label
required property color stemColor
required property int index

width: 56
height: 56
radius: 5
color: stemColor

Skin.ControlKnob {
id: knob
group: root.group
key: `stem_${root.index}_volume`
color: Theme.gainKnobColor
anchors.topMargin: 5
anchors.top: root.top
anchors.horizontalCenter: root.horizontalCenter

arcStart: 0

width: 36
height: 36
}

Text {
anchors.bottom: root.bottom
anchors.horizontalCenter: root.horizontalCenter
text: label
}

Mixxx.ControlProxy {
id: statusControl

group: root.group
key: `stem_${root.index}_mute`
}

Rectangle {
id: statusButton

anchors.left: root.left
anchors.top: root.top
anchors.leftMargin: 4
anchors.topMargin: 4
width: 8
height: width
radius: width / 2
border.width: 1
border.color: Theme.buttonNormalColor
color: statusControl.value ? knob.color : "transparent"

TapHandler {
onTapped: statusControl.value = !statusControl.value
}
}
}
33 changes: 32 additions & 1 deletion src/qml/qmlplayerproxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ QmlPlayerProxy::QmlPlayerProxy(BaseTrackPlayer* pTrackPlayer, QObject* parent)
: QObject(parent),
m_pTrackPlayer(pTrackPlayer),
m_pBeatsModel(new QmlBeatsModel(this)),
m_pHotcuesModel(new QmlCuesModel(this)) {
m_pHotcuesModel(new QmlCuesModel(this))
#ifdef __STEM__
,
m_pStemsModel(std::make_unique<QmlStemsModel>(this))
#endif
{
connect(m_pTrackPlayer,
&BaseTrackPlayer::loadingTrack,
this,
Expand Down Expand Up @@ -129,8 +134,17 @@ void QmlPlayerProxy::slotTrackLoaded(TrackPointer pTrack) {
&Track::cuesUpdated,
this,
&QmlPlayerProxy::slotHotcuesChanged);
#ifdef __STEM__
connect(pTrack.get(),
&Track::stemsUpdated,
this,
&QmlPlayerProxy::slotStemsChanged);
#endif
slotBeatsChanged();
slotHotcuesChanged();
#ifdef __STEM__
slotStemsChanged();
#endif
}
emit trackChanged();
emit trackLoaded();
Expand Down Expand Up @@ -175,6 +189,9 @@ void QmlPlayerProxy::slotTrackChanged() {
emit colorChanged();
emit coverArtUrlChanged();
emit trackLocationUrlChanged();
#ifdef __STEM__
emit stemsChanged();
#endif

emit waveformLengthChanged();
emit waveformTextureChanged();
Expand Down Expand Up @@ -219,6 +236,20 @@ void QmlPlayerProxy::slotBeatsChanged() {
}
}

#ifdef __STEM__
void QmlPlayerProxy::slotStemsChanged() {
VERIFY_OR_DEBUG_ASSERT(m_pStemsModel != nullptr) {
return;
}

const TrackPointer pTrack = m_pCurrentTrack;
if (pTrack) {
m_pStemsModel->setStems(pTrack->getStemInfo());
emit stemsChanged();
}
}
#endif

void QmlPlayerProxy::slotHotcuesChanged() {
VERIFY_OR_DEBUG_ASSERT(m_pHotcuesModel != nullptr) {
return;
Expand Down
19 changes: 19 additions & 0 deletions src/qml/qmlplayerproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "mixer/basetrackplayer.h"
#include "qml/qmlbeatsmodel.h"
#include "qml/qmlcuesmodel.h"
#include "qml/qmlstemsmodel.h"
#include "track/cueinfo.h"
#include "track/track.h"

Expand Down Expand Up @@ -47,6 +48,9 @@ class QmlPlayerProxy : public QObject {

Q_PROPERTY(mixxx::qml::QmlBeatsModel* beatsModel MEMBER m_pBeatsModel CONSTANT);
Q_PROPERTY(mixxx::qml::QmlCuesModel* hotcuesModel MEMBER m_pHotcuesModel CONSTANT);
#ifdef __STEM__
Q_PROPERTY(mixxx::qml::QmlStemsModel* stemsModel READ getStemsModel CONSTANT);
#endif

public:
explicit QmlPlayerProxy(BaseTrackPlayer* pTrackPlayer, QObject* parent = nullptr);
Expand Down Expand Up @@ -82,13 +86,22 @@ class QmlPlayerProxy : public QObject {
Q_INVOKABLE void loadTrackFromLocation(const QString& trackLocation, bool play = false);
Q_INVOKABLE void loadTrackFromLocationUrl(const QUrl& trackLocationUrl, bool play = false);

#ifdef __STEM__
QmlStemsModel* getStemsModel() const {
return m_pStemsModel.get();
}
#endif

public slots:
void slotTrackLoaded(TrackPointer pTrack);
void slotLoadingTrack(TrackPointer pNewTrack, TrackPointer pOldTrack);
void slotTrackChanged();
void slotWaveformChanged();
void slotBeatsChanged();
void slotHotcuesChanged();
#ifdef __STEM__
void slotStemsChanged();
#endif

void setArtist(const QString& artist);
void setTitle(const QString& title);
Expand Down Expand Up @@ -126,6 +139,9 @@ class QmlPlayerProxy : public QObject {
void coverArtUrlChanged();
void trackLocationUrlChanged();
void cuesChanged();
#ifdef __STEM__
void stemsChanged();
#endif

void loadTrackFromLocationRequested(const QString& trackLocation, bool play);

Expand All @@ -140,6 +156,9 @@ class QmlPlayerProxy : public QObject {
TrackPointer m_pCurrentTrack;
QmlBeatsModel* m_pBeatsModel;
QmlCuesModel* m_pHotcuesModel;
#ifdef __STEM__
std::unique_ptr<QmlStemsModel> m_pStemsModel;
#endif
};

} // namespace qml
Expand Down
Loading

0 comments on commit 36af073

Please sign in to comment.