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

feat: controller screen renderer #11407

Merged
merged 31 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
10cfd2f
feat: controller screen rendering
acolombier Mar 27, 2024
ba4d030
Adding some more inline doc and addressing clang-tidy warnings
acolombier Apr 6, 2024
b8b7f91
Merge remote-tracking branch 'upstream/main' into HEAD
acolombier Apr 6, 2024
f1487a0
Fix typo in test
acolombier Apr 9, 2024
feeb892
Merge remote-tracking branch 'upstream/main' into feat/controller-scr…
acolombier Apr 11, 2024
6d5fb99
Removing unused QML Scene3D import
acolombier Apr 12, 2024
a204405
Fix typo and rename confusing symbols
acolombier May 4, 2024
2be3c21
Merge remote-tracking branch 'upstream/main' into feat/controller-scr…
acolombier May 8, 2024
676cd90
Use std for duration and address couple of PR nits
acolombier May 8, 2024
61ec210
Fixing assert, comment, typo const and wait for thread
acolombier May 8, 2024
6bb2235
Fix test
acolombier May 8, 2024
e864684
Remove unnecessary mutex and removing code duplication
acolombier May 8, 2024
10cb8a6
Updating var naming, add comments and small refactor
acolombier May 9, 2024
ede6993
Fix clazy warning
acolombier May 9, 2024
c815d09
Enforce OpenGL as QQuickWindow RHI
acolombier May 12, 2024
42158b5
Comment and nits
acolombier May 13, 2024
ea12d82
Improve rendering engine teardown
acolombier May 15, 2024
b1b9e64
Merge remote-tracking branch 'upstream/main' into feat/controller-scr…
acolombier May 15, 2024
a87fd88
Fix linting
acolombier May 15, 2024
633c84d
Move the engine pause logic in a dedicated object
acolombier May 16, 2024
ee6dfe5
Some more nits
acolombier May 16, 2024
d60c2bd
Explicit copy of the image frame
acolombier May 16, 2024
d9b135c
use bit_cast
acolombier May 17, 2024
65d3286
Fix grammar issues
acolombier May 19, 2024
b6c158b
Add mapping resource by struct instead or arg
acolombier May 19, 2024
5861649
Don't use callFunctionOnObjects for QML
acolombier May 19, 2024
b63577c
Nits
acolombier May 24, 2024
cb9a5c2
Comments and co
acolombier May 24, 2024
6197a07
Use stack allocation for QML component
acolombier May 25, 2024
df39da0
Merge remote-tracking branch 'upstream/main' into feat/controller-scr…
acolombier May 31, 2024
d7ce6d8
Use QStringLiteral on ScopedTimer
acolombier Jun 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ jobs:
-DCMAKE_BUILD_TYPE=Debug \
-DOPTIMIZE=off \
-DQT6=ON \
-DQML=ON \
-DCOVERAGE=ON \
-DWARNINGS_FATAL=OFF \
-DDEBUG_ASSERTIONS_FATAL=OFF \
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ jobs:
-DMACOS_BUNDLE=ON
-DMODPLUG=ON
-DQT6=ON
-DQML=OFF
Copy link
Member

Choose a reason for hiding this comment

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

Hm, this PR seems to have broken the build with QML on macOS (which is the default) and since we've disabled it in CI, some issues seem to have flown under the radar here... I'll have a quick look at how easy that would be to fix

-DWAVPACK=ON
-DVCPKG_TARGET_TRIPLET=x64-osx-min1100-release
-DVCPKG_DEFAULT_HOST_TRIPLET=x64-osx-min1100-release
Expand All @@ -71,6 +72,7 @@ jobs:
-DMACOS_BUNDLE=ON
-DMODPLUG=ON
-DQT6=ON
-DQML=OFF
-DWAVPACK=ON
-DVCPKG_TARGET_TRIPLET=arm64-osx-min1100-release
-DVCPKG_DEFAULT_HOST_TRIPLET=x64-osx-min1100-release
Expand Down Expand Up @@ -101,6 +103,7 @@ jobs:
-DMEDIAFOUNDATION=ON
-DMODPLUG=ON
-DQT6=ON
-DQML=OFF
-DWAVPACK=ON
-DVCPKG_TARGET_TRIPLET=x64-windows-release
-DVCPKG_DEFAULT_HOST_TRIPLET=x64-windows-release
Expand Down
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,13 @@ if (NOT QML)
src/control/controlmodel.cpp
src/control/controlsortfiltermodel.cpp
)
else()
target_sources(mixxx-lib PRIVATE
# The following source depends of QML being available but aren't part of the new QML UI
src/controllers/rendering/controllerrenderingengine.cpp
src/controllers/controllerenginethreadcontrol.cpp
src/controllers/controllerscreenpreview.cpp
)
endif()
if(QOPENGL)
target_sources(mixxx-lib PRIVATE
Expand Down Expand Up @@ -2176,7 +2183,14 @@ add_executable(mixxx-test
src/test/wwidgetstack_test.cpp
src/test/waveform_upgrade_test.cpp
src/util/moc_included_test.cpp
src/test/helpers/log_test.cpp
)
if (QML)
target_sources(mixxx-test PRIVATE
src/test/controller_mapping_file_handler_test.cpp
src/test/controllerrenderingengine_test.cpp
)
endif()
find_package(GTest CONFIG REQUIRED)
set_target_properties(mixxx-test PROPERTIES AUTOMOC ON)
target_link_libraries(mixxx-test PRIVATE mixxx-lib mixxx-gitinfostore GTest::gtest GTest::gmock)
Expand Down
22 changes: 22 additions & 0 deletions res/controllers/Dummy Device Screen.hid.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version='1.0' encoding='utf-8'?>
<MixxxControllerPreset mixxxVersion="2.4.0" schemaVersion="1">
<info>
<name>Dummy Device (Screens)</name>
<author>A. Colombier</author>
<description>Dummy device screens</description>
<devices>
<product protocol="hid" vendor_id="0xdead" product_id="0xbeaf" />
</devices>
</info>
<controller id="DummyDevice">
<screens>
<screen identifier="main" width="480" height="360" targetFps="20" pixelType="RBGA" splashoff="500" />
<screen identifier="jog" width="128" height="128" targetFps="5" pixelType="RBGA" />
</screens>
<scriptfiles>
<file filename="DummyDeviceDefaultScreen.qml" />
</scriptfiles>
<qmllibraries>
</qmllibraries>
</controller>
</MixxxControllerPreset>
305 changes: 305 additions & 0 deletions res/controllers/DummyDeviceDefaultScreen.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
import QtQuick 2.15
import QtQuick.Window 2.3

import QtQuick.Controls 2.15
import QtQuick.Shapes 1.11
import QtQuick.Layouts 1.3
import QtQuick.Window 2.15

import Qt5Compat.GraphicalEffects

import Mixxx 1.0 as Mixxx
import Mixxx.Controls 1.0 as MixxxControls

import "." as Skin

Item {
id: root

required property string screenId
property color fontColor: Qt.rgba(242/255,242/255,242/255, 1)
property color smallBoxBorder: Qt.rgba(44/255,44/255,44/255, 1)

property string group: "[Channel1]"
property var deckPlayer: Mixxx.PlayerManager.getPlayer(root.group)

function init(controlerName, isDebug) {
console.log(`Screen ${root.screenId} has started`)
switch (root.screenId) {
case "jog":
loader.sourceComponent = jog
break;
default:
loader.sourceComponent = main
}
}

function shutdown() {
console.log(`Screen ${root.screenId} is stopping`)
loader.sourceComponent = splash
}

// function transformFrame(input: ArrayBuffer, timestamp: date) {
acolombier marked this conversation as resolved.
Show resolved Hide resolved
function transformFrame(input, timestamp) {
return new ArrayBuffer(0);
}

Mixxx.ControlProxy {
group: root.group
key: "track_loaded"

onValueChanged: (value) => {
deckPlayer = Mixxx.PlayerManager.getPlayer(root.group)
}
}

Timer {
id: channelchange

interval: 2000
repeat: true
running: true

onTriggered: {
root.group = root.group === "[Channel1]" ? "[Channel2]" : "[Channel1]"
Copy link
Member

Choose a reason for hiding this comment

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

do we care about 4-deck support here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The "Dummy Screen" mapping was only put there to allow anyone to test this feature without a S4 Mk3 device. I think this mapping can be removed before we merge

Copy link
Member

Choose a reason for hiding this comment

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

that seems like it would be a useful feature, though? would this help developers create screen designs for controllers of arbitrary sizes without needing to own the devices? Also too, it might help with the creation of tests.

Copy link
Member

Choose a reason for hiding this comment

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

(and we will need to test switchable 4 deck support, I would imagine)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Perhaps this could go in the tools folder then? My concern being, we probably shouldn't ship this mapping as part of the the distribution. This could however be a good starting point for anyone wishing to test this feature and make the most of the screen rendering without using the physical device, which may help for design and testing. What do you think? Maybe I can put that as a snippet in the tools/README.md?

Copy link
Member

Choose a reason for hiding this comment

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

Ideally it could be included in the developer builds only, so that it is still regularly built by CI. It could be in something like res/controllers/testing/ . But if it's easier to put it somewhere else for now that's fine too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • Move DummyMapping to tools folder before merging

deckPlayer = Mixxx.PlayerManager.getPlayer(root.group)
}
}

Component {
id: splash
Rectangle {
color: "black"
anchors.fill: parent
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
source: "../images/templates/logo_mixxx.png"
}
}
}

Component {
id: jog

Rectangle {
anchors.fill: parent
color: "black"

Image {
id: artwork
anchors.fill: parent
visible: deckPlayer.trackLocationUrl.toString().length !== 0

source: deckPlayer.coverArtUrl ?? "../images/templates/logo_mixxx.png"
height: 100
width: 100
fillMode: Image.PreserveAspectFit
}

Text {
visible: deckPlayer.trackLocationUrl.toString().length === 0

text: qsTr("No Track Loaded")
font.pixelSize: 12
font.family: "Noto Sans"
font.letterSpacing: -1
color: "white"
}
}
}

Component {
id: main

Rectangle {
id: debugValue
anchors.fill: parent
color: 'black'

antialiasing: true

ColumnLayout {
id: column
anchors.fill: parent
anchors.leftMargin: 0
anchors.rightMargin: 0
anchors.topMargin: 0
anchors.bottomMargin: 0
spacing: 6

RowLayout {
Layout.fillWidth: true
spacing: 0

Repeater {
id: debugColor

model: [
"black",
"white",
"red",
"green",
"blue",
Qt.rgba(0, 1, 1),
]

Rectangle {
required property var modelData

color: modelData
Layout.fillWidth: true
height: 80
}
}
}

RowLayout {
anchors.leftMargin: 6
anchors.rightMargin: 6
anchors.topMargin: 6
anchors.bottomMargin: 6

Layout.fillWidth: true
Layout.fillHeight: true
spacing: 6

Rectangle {
color: 'transparent'
Layout.fillWidth: true
Layout.fillHeight: true
Text {
text: qsTr("Group")
font.pixelSize: 24
font.family: "Noto Sans"
font.letterSpacing: -1
color: fontColor
}
}

Rectangle {
color: 'transparent'
Layout.fillWidth: true
Layout.fillHeight: true
Text {
text: `${root.group}`
font.pixelSize: 24
font.family: "Noto Sans"
font.letterSpacing: -1
color: fontColor
}
}
}

RowLayout {
anchors.leftMargin: 6
anchors.rightMargin: 6
anchors.topMargin: 6
anchors.bottomMargin: 6

Layout.fillWidth: true
Layout.fillHeight: true
spacing: 6

Rectangle {
color: 'transparent'
Layout.fillWidth: true
Layout.fillHeight: true
Text {
text: qsTr("Widget")
font.pixelSize: 24
font.family: "Noto Sans"
font.letterSpacing: -1
color: fontColor
}
}

Rectangle {
color: 'transparent'
Layout.fillWidth: true
Layout.fillHeight: true

Skin.HotcueButton {
anchors.fill: parent

hotcueNumber: 1
group: root.group
}
}
}

Repeater {
model: [{
controllerKey: "beatloop_size",
title: "Beatloop Size"
}, {
controllerKey: "track_samples",
title: "Track sample"
}, {
controllerKey: "track_samplerate",
title: "Track sample rate"
}, {
controllerKey: "playposition",
title: "Play position"
}, {
controllerKey: "rate_ratio",
title: "Rate ratio"
}, {
controllerKey: "waveform_zoom",
title: "Waveform zoom"
}
]

RowLayout {
id: row
anchors.leftMargin: 6
anchors.rightMargin: 6
anchors.topMargin: 6
anchors.bottomMargin: 6
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 6
required property var modelData

Mixxx.ControlProxy {
id: mixxxValue
group: root.group
key: modelData.controllerKey
}

Rectangle {
color: 'transparent'
Layout.fillWidth: true
Layout.fillHeight: true
Text {
text: qsTr(modelData.title)
font.pixelSize: 24
font.family: "Noto Sans"
font.letterSpacing: -1
color: fontColor
}
}

Rectangle {
color: 'transparent'
Layout.fillWidth: true
Layout.fillHeight: true
Text {
text: `${mixxxValue.value}`
font.pixelSize: 24
font.family: "Noto Sans"
font.letterSpacing: -1
color: fontColor
}
}
}
}
}
}
}
Loader {
id: loader
anchors.fill: parent
sourceComponent: splash
}
}
Loading