diff --git a/Commons/Settings.qml b/Commons/Settings.qml index b4b240f..833426d 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -213,6 +213,8 @@ Singleton { property JsonObject audio audio: JsonObject { + property bool showMiniplayerAlbumArt: false + property bool showMiniplayerCava: false property string visualizerType: "linear" property int volumeStep: 5 } diff --git a/Modules/Bar/MediaMini.qml b/Modules/Bar/MediaMini.qml index 5a276c8..cd6dedb 100644 --- a/Modules/Bar/MediaMini.qml +++ b/Modules/Bar/MediaMini.qml @@ -2,6 +2,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell +import qs.Modules.Audio import qs.Commons import qs.Services import qs.Widgets @@ -40,19 +41,102 @@ Row { anchors.leftMargin: Style.marginS * scaling anchors.rightMargin: Style.marginS * scaling + Loader { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + active: Settings.data.audio.showMiniplayerCava && Settings.data.audio.visualizerType == "linear" && MediaService.isPlaying + z: 0 + + sourceComponent: LinearSpectrum { + width: mainContainer.width - Style.marginS * scaling + height: 20 * scaling + values: CavaService.values + fillColor: Color.mPrimary + opacity: 0.4 + } + + Loader { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + active: Settings.data.audio.showMiniplayerCava && Settings.data.audio.visualizerType == "mirrored" && MediaService.isPlaying + z: 0 + + sourceComponent: MirroredSpectrum { + width: mainContainer.width - Style.marginS * scaling + height: mainContainer.height - Style.marginS * scaling + values: CavaService.values + fillColor: Color.mPrimary + opacity: 0.4 + } + } + + Loader { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + active: Settings.data.audio.showMiniplayerCava && Settings.data.audio.visualizerType == "wave" && MediaService.isPlaying + z: 0 + + sourceComponent: WaveSpectrum { + width: mainContainer.width - Style.marginS * scaling + height: mainContainer.height - Style.marginS * scaling + values: CavaService.values + fillColor: Color.mPrimary + opacity: 0.4 + } + } + } + Row { id: row anchors.verticalCenter: parent.verticalCenter spacing: Style.marginXS * scaling + z: 1 // Above the visualizer - // Window icon NIcon { - id: windowIcon - text: MediaService.isPlaying ? "pause" : "play_arrow" - font.pointSize: Style.fontSizeL * scaling - verticalAlignment: Text.AlignVCenter - anchors.verticalCenter: parent.verticalCenter - visible: getTitle() !== "" + id: windowIcon + text: MediaService.isPlaying ? "pause" : "play_arrow" + font.pointSize: Style.fontSizeL * scaling + verticalAlignment: Text.AlignVCenter + anchors.verticalCenter: parent.verticalCenter + visible: !Settings.data.audio.showMiniplayerAlbumArt && getTitle() !== "" && !trackArt.visible + } + + Column { + anchors.verticalCenter: parent.verticalCenter + visible: Settings.data.audio.showMiniplayerAlbumArt + + Rectangle { + width: 16 * scaling + height: 16 * scaling + radius: width * 0.5 + color: Color.transparent + antialiasing: true + clip: true + + NImageRounded { + id: trackArt + visible: MediaService.trackArtUrl.toString() !== "" + anchors.fill: parent + anchors.verticalCenter: parent.verticalCenter + anchors.margins: scaling + imagePath: MediaService.trackArtUrl + fallbackIcon: MediaService.isPlaying ? "pause" : "play_arrow" + borderWidth: 0 + border.color: Color.transparent + imageRadius: width + antialiasing: true + } + + // Fallback icon when no album art available + NIcon { + id: windowIconFallback + text: MediaService.isPlaying ? "pause" : "play_arrow" + font.pointSize: Style.fontSizeL * scaling + verticalAlignment: Text.AlignVCenter + anchors.verticalCenter: parent.verticalCenter + visible: getTitle() !== "" && !trackArt.visible + } + } } NText { diff --git a/Modules/SettingsPanel/Tabs/AudioTab.qml b/Modules/SettingsPanel/Tabs/AudioTab.qml index ffc225e..e10af61 100644 --- a/Modules/SettingsPanel/Tabs/AudioTab.qml +++ b/Modules/SettingsPanel/Tabs/AudioTab.qml @@ -219,6 +219,47 @@ ColumnLayout { } } } + + // Divider + NDivider { + Layout.fillWidth: true + Layout.topMargin: Style.marginL * scaling + Layout.bottomMargin: Style.marginM * scaling + } + + // AudioService Visualizer Category + ColumnLayout { + spacing: Style.marginS * scaling + Layout.fillWidth: true + + NText { + text: "Bar Media Player" + font.pointSize: Style.fontSizeXXL * scaling + font.weight: Style.fontWeightBold + color: Color.mOnSurface + Layout.bottomMargin: Style.marginS * scaling + } + + // Miniplayer section + NToggle { + label: "Show Album Art In Bar Media Player" + description: "Show the album art of the currently playing song next to the title." + checked: Settings.data.audio.showMiniplayerAlbumArt + onToggled: checked => { + Settings.data.audio.showMiniplayerAlbumArt = checked + } + } + + NToggle { + label: "Show Audio Visualizer In Bar Media Player" + description: "Shows an audio visualizer in the background of the miniplayer." + checked: Settings.data.audio.showMiniplayerCava + onToggled: checked => { + Settings.data.audio.showMiniplayerCava = checked + } + } + } + // Divider NDivider { diff --git a/Services/CavaService.qml b/Services/CavaService.qml index dae2f61..3600d62 100644 --- a/Services/CavaService.qml +++ b/Services/CavaService.qml @@ -9,7 +9,7 @@ Singleton { id: root property var values: Array(barsCount).fill(0) - property int barsCount: 32 + property int barsCount: 24 property var config: ({ "general": { @@ -37,7 +37,7 @@ Singleton { Process { id: process stdinEnabled: true - running: (Settings.data.audio.visualizerType !== "none") && PanelService.sidePanel.active + running: (Settings.data.audio.visualizerType !== "none") && (PanelService.sidePanel.active || Settings.data.audio.showMiniplayerCava) command: ["cava", "-p", "/dev/stdin"] onExited: { stdinEnabled = true