Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
acolombier committed Apr 11, 2024
1 parent e7be571 commit eaefb08
Show file tree
Hide file tree
Showing 9 changed files with 307 additions and 31 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3449,6 +3449,12 @@ if (STEM)
src/track/steminfoimporter.cpp
src/track/steminfo.cpp # TODO precompiled header?
)
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
138 changes: 112 additions & 26 deletions res/qml/EqColumn.qml
Original file line number Diff line number Diff line change
@@ -1,44 +1,130 @@
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
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

Rectangle {
id: stemRect
width: 56
height: 56
color: stem.color
radius: 5

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

arcStart: 0

width: 36
height: 36
}
Text {
anchors.bottom: stemRect.bottom
anchors.horizontalCenter: stemRect.horizontalCenter
text: label
}
}
}
}
}
Column {
id: eq
spacing: 4
width: 10
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
38 changes: 34 additions & 4 deletions src/engine/channels/enginedeck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
#include "engine/enginepregain.h"
#include "engine/enginevumeter.h"
#include "moc_enginedeck.cpp"
#include "track/track.h"
#include "util/sample.h"

namespace {
constexpr int kMaxSupportedStem = 4;
}

Check warning on line 15 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / clang-tidy

anonymous namespace not terminated with a closing comment [google-readability-namespace-comments]

EngineDeck::EngineDeck(
const ChannelHandleAndGroup& handleGroup,
UserSettingsPointer pConfig,
Expand All @@ -20,6 +25,7 @@ EngineDeck::EngineDeck(
/*isTalkoverChannel*/ false,
primaryDeck),
m_pConfig(pConfig),
m_pStemCount(std::make_unique<ControlObject>(ConfigKey(getGroup(), "stem_count"))),
m_pInputConfigured(new ControlObject(ConfigKey(getGroup(), "input_configured"))),
m_pPassing(new ControlPushButton(ConfigKey(getGroup(), "passthrough"))) {
m_pInputConfigured->setReadOnly();
Expand All @@ -36,6 +42,23 @@ EngineDeck::EngineDeck(

m_pPregain = new EnginePregain(getGroup());
m_pBuffer = new EngineBuffer(getGroup(), pConfig, this, pMixingEngine);
connect(m_pBuffer, &EngineBuffer::trackLoaded, this, &EngineDeck::slotTrackLoaded);

m_stemGain.reserve(kMaxSupportedStem);
for (int i = 0; i < kMaxSupportedStem; i++) {
m_stemGain.emplace_back(std::make_unique<ControlObject>(
ConfigKey(getGroup(), QString("stem_%1_volume").arg(i)),
true,
false,
false,
1.0));
}
}

void EngineDeck::slotTrackLoaded(TrackPointer pNewTrack,
TrackPointer) {
int stemCount = pNewTrack->getStemInfo().size();
m_pStemCount->set(stemCount);
}

EngineDeck::~EngineDeck() {
Expand All @@ -58,14 +81,21 @@ void EngineDeck::processStem(CSAMPLE* pOut, const int iBufferSize) {
for (int c = 0; c < stereoChannelCount; c++) {
// TODO(XXX): apply stem gain or skip muted stem
if (!c) {
pOut[2 * i] = m_stemBuffer.data()[2 * stereoChannelCount * i];
pOut[2 * i + 1] = m_stemBuffer.data()[2 * stereoChannelCount * i + 1];
pOut[2 * i] = m_stemBuffer.data()[2 * stereoChannelCount * i] *

Check failure on line 84 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Werror=float-conversion]

Check warning on line 84 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / coverage

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Wfloat-conversion]
m_stemGain[c]->get();
pOut[2 * i + 1] =
m_stemBuffer.data()[2 * stereoChannelCount * i + 1] *

Check failure on line 87 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Werror=float-conversion]

Check warning on line 87 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / coverage

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Wfloat-conversion]
m_stemGain[c]->get();
} else {
pOut[2 * i] += m_stemBuffer.data()[2 * stereoChannelCount * i + 2 * c];
pOut[2 * i] +=
m_stemBuffer
.data()[2 * stereoChannelCount * i + 2 * c] *
m_stemGain[c]->get();

Check failure on line 93 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Werror=float-conversion]

Check warning on line 93 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / coverage

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Wfloat-conversion]
pOut[2 * i + 1] +=
m_stemBuffer
.data()[2 * stereoChannelCount * i +
2 * c + 1];
2 * c + 1] *
m_stemGain[c]->get();

Check failure on line 98 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Werror=float-conversion]

Check warning on line 98 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / coverage

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Wfloat-conversion]
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/engine/channels/enginedeck.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "engine/channels/enginechannel.h"
#include "preferences/usersettings.h"
#include "soundio/soundmanagerutil.h"
#include "track/track_decl.h"
#include "util/samplebuffer.h"

class EnginePregain;
Expand Down Expand Up @@ -69,6 +70,7 @@ class EngineDeck : public EngineChannel, public AudioDestination {
public slots:
void slotPassthroughToggle(double v);
void slotPassthroughChangeRequest(double v);
void slotTrackLoaded(TrackPointer pNewTrack, TrackPointer);

private:
// Process multiple channels and mix them together into the passed buffer
Expand All @@ -80,6 +82,8 @@ class EngineDeck : public EngineChannel, public AudioDestination {

// Stem buffer used to retrieve all the channel to mix together
mixxx::SampleBuffer m_stemBuffer;
std::unique_ptr<ControlObject> m_pStemCount;
std::vector<std::unique_ptr<ControlObject>> m_stemGain;

// Begin vinyl passthrough fields
QScopedPointer<ControlObject> m_pInputConfigured;
Expand Down
35 changes: 34 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,22 @@ void QmlPlayerProxy::slotBeatsChanged() {
}
}

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

QList<StemInfo> stems;

Check warning on line 245 in src/qml/qmlplayerproxy.cpp

View workflow job for this annotation

GitHub Actions / clazy

unused QList<StemInfo> [-Wclazy-unused-non-trivial-variable]

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
17 changes: 17 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,20 @@ class QmlPlayerProxy : public QObject {
Q_INVOKABLE void loadTrackFromLocation(const QString& trackLocation, bool play = false);
Q_INVOKABLE void loadTrackFromLocationUrl(const QUrl& trackLocationUrl, bool play = false);

QmlStemsModel* getStemsModel() const {
return m_pStemsModel.get();

Check failure on line 90 in src/qml/qmlplayerproxy.h

View workflow job for this annotation

GitHub Actions / Windows 2019 (MSVC)

'm_pStemsModel': undeclared identifier
}

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 +137,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 +154,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 eaefb08

Please sign in to comment.