Merge pull request #12 from ferrreo/misc-music-fixes

fix: misc music fixes + add visualizer options
This commit is contained in:
ferrreo 2025-07-14 23:41:54 +01:00 committed by GitHub
commit 66f11eaa1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 129 additions and 19 deletions

View file

@ -9,7 +9,7 @@ import qs.Components
Item {
id: mediaControl
width: visible ? mediaRow.width : 0
height: 32
height: 36
visible: Settings.showMediaInBar && MusicManager.currentPlayer
RowLayout {

View file

@ -20,6 +20,7 @@ Scope {
mono_option: monoOption,
}
})
property var values: Array(count).fill(0) // 0 <= value <= 1
Process {
@ -28,7 +29,7 @@ Scope {
stdinEnabled: true
running: MusicManager.isPlaying
command: ["cava", "-p", "/dev/stdin"]
onExited: { stdinEnabled = true; index = 0 }
onExited: { stdinEnabled = true; index = 0; values = []; }
onStarted: {
const iniParts = []
for (const k in config) {
@ -55,9 +56,6 @@ Scope {
newValues[i + process.index] = Math.min(data.charCodeAt(i), 128) / 128
}
process.index += data.length
if (newValues.length !== values.length) {
console.log("length!", values.length, newValues.length)
}
values = newValues
}
}

View file

@ -1,5 +1,6 @@
import QtQuick
import qs.Components
import qs.Settings
Item {
id: root
@ -9,9 +10,14 @@ Item {
property color strokeColor: "#fff"
property int strokeWidth: 0
property var values: []
property int usableOuter: 48
width: outerRadius * 2
height: outerRadius * 2
width: usableOuter * 2
height: usableOuter * 2
onOuterRadiusChanged: () => {
usableOuter = Settings.visualizerType === "fire" ? outerRadius * 0.85 : outerRadius;
}
Repeater {
model: root.values.length
@ -19,23 +25,33 @@ Item {
property real value: root.values[index]
property real angle: (index / root.values.length) * 360
width: Math.max(2, (root.innerRadius * 2 * Math.PI) / root.values.length - 4)
height: value * (root.outerRadius - root.innerRadius)
height: Settings.visualizerType === "diamond" ? value * 2 * (usableOuter - root.innerRadius) : value * (usableOuter - root.innerRadius)
radius: width / 2
color: root.fillColor
border.color: root.strokeColor
border.width: root.strokeWidth
antialiasing: true
x: root.width / 2 + (root.innerRadius) * Math.cos(Math.PI/2 + 2 * Math.PI * index / root.values.length) - width / 2
y: root.height / 2 - (root.innerRadius) * Math.sin(Math.PI/2 + 2 * Math.PI * index / root.values.length) - height
x: Settings.visualizerType === "radial" ? root.width / 2 - width / 2 : root.width / 2 + root.innerRadius * Math.cos(Math.PI / 2 + 2 * Math.PI * index / root.values.length) - width / 2
transform: Rotation {
origin.x: width / 2
origin.y: height
angle: -angle
y: Settings.visualizerType === "radial" ? root.height / 2 - height : Settings.visualizerType === "diamond" ? root.height / 2 - root.innerRadius * Math.sin(Math.PI / 2 + 2 * Math.PI * index / root.values.length) - height / 2 : root.height / 2 - root.innerRadius * Math.sin(Math.PI / 2 + 2 * Math.PI * index / root.values.length) - height
transform: [
Rotation {
origin.x: width / 2
origin.y: Settings.visualizerType === "diamond" ? height / 2 : height
angle: Settings.visualizerType === "radial" ? (index / root.values.length) * 360 : Settings.visualizerType === "fire" ? 0 : (index / root.values.length) * 360 - 90
},
Translate {
x: Settings.visualizerType === "radial" ? root.innerRadius * Math.cos(2 * Math.PI * index / root.values.length) : 0
y: Settings.visualizerType === "radial" ? root.innerRadius * Math.sin(2 * Math.PI * index / root.values.length) : 0
}
]
Behavior on height {
SmoothedAnimation {
duration: 120
}
}
Behavior on height { SmoothedAnimation { duration: 120 } }
}
}
}
}

View file

@ -29,6 +29,7 @@ QtObject {
property int transitionFps: 60
property string transitionType: "random"
property real transitionDuration: 1.1
property string visualizerType: "radial" // Options: "fire", "diamond", "radial"
// Settings persistence
property var settings: Settings {
@ -60,6 +61,7 @@ QtObject {
transitionFps = settings.value("transitionFps", transitionFps)
transitionType = settings.value("transitionType", transitionType)
transitionDuration = settings.value("transitionDuration", transitionDuration)
visualizerType = settings.value("visualizerType", visualizerType)
WallpaperManager.setCurrentWallpaper(currentWallpaper, true);
}
@ -82,6 +84,7 @@ QtObject {
settings.setValue("transitionFps", transitionFps)
settings.setValue("transitionType", transitionType)
settings.setValue("transitionDuration", transitionDuration)
settings.setValue("visualizerType", visualizerType)
settings.sync()
}

View file

@ -7,7 +7,7 @@ import qs.Settings
Rectangle {
id: profileSettingsCard
Layout.fillWidth: true
Layout.preferredHeight: 300
Layout.preferredHeight: 340
color: Theme.surface
radius: 18
border.color: "transparent"
@ -19,6 +19,8 @@ Rectangle {
signal showSystemInfoChanged(bool showSystemInfoInBar)
property bool showMediaInBar: false
signal showMediaChanged(bool showMediaInBar)
property string visualizerType: Settings.visualizerType
signal visualizerTypeUpdated(string type)
ColumnLayout {
anchors.fill: parent
@ -284,6 +286,88 @@ Rectangle {
}
}
// Visualizer Type Selection
RowLayout {
spacing: 8
Layout.fillWidth: true
Text {
text: "Visualizer Type"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
Layout.alignment: Qt.AlignVCenter
}
Item {
Layout.fillWidth: true
}
// Dropdown for visualizer type
Rectangle {
width: 120
height: 36
radius: 8
color: Theme.surfaceVariant
border.color: Theme.outline
border.width: 1
Text {
id: visualizerTypeText
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: visualizerType === "fire" ? "Fire" :
visualizerType === "diamond" ? "Diamond" :
visualizerType === "radial" ? "Radial" : "Radial"
font.pixelSize: 13
color: Theme.textPrimary
}
Text {
text: "arrow_drop_down"
font.family: "Material Symbols Outlined"
font.pixelSize: 20
color: Theme.textPrimary
anchors.right: parent.right
anchors.rightMargin: 8
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
visualizerTypeMenu.open()
}
}
Menu {
id: visualizerTypeMenu
width: 120
y: parent.height
MenuItem {
text: "Fire"
onTriggered: {
visualizerTypeUpdated("fire")
}
}
MenuItem {
text: "Diamond"
onTriggered: {
visualizerTypeUpdated("diamond")
}
}
MenuItem {
text: "Radial"
onTriggered: {
visualizerTypeUpdated("radial")
}
}
}
}
}
// Video Path Input Row
RowLayout {
spacing: 8

View file

@ -37,6 +37,7 @@ PanelWindow {
property real tempTransitionDuration: Settings.transitionDuration
property bool tempShowSystemInfoInBar: Settings.showSystemInfoInBar
property bool tempShowMediaInBar: Settings.showMediaInBar
property string tempVisualizerType: Settings.visualizerType
Rectangle {
anchors.fill: parent
@ -151,6 +152,10 @@ PanelWindow {
onShowMediaChanged: function (showMediaInBar) {
tempShowMediaInBar = showMediaInBar;
}
visualizerType: tempVisualizerType
onVisualizerTypeUpdated: function (type) {
tempVisualizerType = type;
}
}
}
CollapsibleCategory {
@ -236,6 +241,7 @@ PanelWindow {
Settings.transitionDuration = tempTransitionDuration;
Settings.showSystemInfoInBar = tempShowSystemInfoInBar;
Settings.showMediaInBar = tempShowMediaInBar;
Settings.visualizerType = tempVisualizerType;
Settings.saveSettings();
if (typeof weather !== 'undefined' && weather) {
weather.fetchCityWeather();
@ -266,6 +272,9 @@ PanelWindow {
tempTransitionFps = Settings.transitionFps;
tempTransitionType = Settings.transitionType;
tempTransitionDuration = Settings.transitionDuration;
tempShowSystemInfoInBar = Settings.showSystemInfoInBar;
tempShowMediaInBar = Settings.showMediaInBar;
tempVisualizerType = Settings.visualizerType;
visible = true;
// Force focus on the text input after a short delay

View file

@ -51,7 +51,7 @@ Rectangle {
anchors.fill: parent
anchors.margins: 18
spacing: 12
visible: currentPlayer
visible: !!MusicManager.currentPlayer
// Album art and spectrum
RowLayout {