From 243d64266aacdbfd4a20ea580ce8c03cf4ae227f Mon Sep 17 00:00:00 2001 From: Martino Pilia Date: Sun, 10 Mar 2024 19:02:51 +0100 Subject: [PATCH] Update to KF6 KF5 will no longer be supported. To install on Plasma 5, use the commit prior to this. * KF6 API: https://develop.kde.org/docs/plasma/widget/porting_kf6 * Move the players from the fullRepresentation to the main item. This allows starting playback before the fullRepresentation is initialised, e.g. automatically at startup before the plasmoid is ever manually activated. --- CMakeLists.txt | 14 +-- README.md | 22 ++--- icons/CMakeLists.txt | 6 +- plasmoid/contents/config/config.qml | 4 +- plasmoid/contents/js/scripts.js | 27 ++---- plasmoid/contents/ui/AddNoisePopup.qml | 65 +++++++------ plasmoid/contents/ui/NoiseListItem.qml | 48 ++++------ plasmoid/contents/ui/main.qml | 124 +++++++++++++++++-------- plasmoid/contents/ui/settings.qml | 17 ++-- plasmoid/metadata.desktop | 23 ----- plasmoid/metadata.json | 30 ++++++ 11 files changed, 207 insertions(+), 173 deletions(-) delete mode 100644 plasmoid/metadata.desktop create mode 100644 plasmoid/metadata.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cf0e5a..2445873 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,18 @@ -cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) +cmake_minimum_required(VERSION 3.16 FATAL_ERROR) -set(QT_MIN_VERSION "5.3.0") -set(KF5_MIN_VERSION "5.0.0") +project(AmbientNoise) -find_package(ECM 0.0.11 REQUIRED NO_MODULE) +find_package(ECM 6.0.0 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) -include(KDEInstallDirs) +include(KDEInstallDirs6) include(KDECMakeSettings) include(KDECompilerSettings) -find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Quick) -find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Plasma) +find_package(Qt6 6.5.0 CONFIG REQUIRED Quick Multimedia) +find_package(KF6 6.0.0 REQUIRED) +find_package(Plasma REQUIRED) add_subdirectory(icons) add_subdirectory(translations) diff --git a/README.md b/README.md index 73121cb..db45b2e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Ambient noise applet for Plasma 5 +# Ambient noise applet for Plasma 6 [![Checks](https://github.com/m-pilia/plasma-applet-ambientnoise/workflows/Checks/badge.svg)](https://github.com/m-pilia/plasma-applet-ambientnoise/actions/workflows/checks.yml) @@ -24,21 +24,22 @@ The applet can be installed locally with ```bash git clone https://github.com/m-pilia/plasma-applet-ambientnoise cd plasma-applet-ambientnoise/ -kpackagetool5 -t Plasma/Applet --install plasmoid +kpackagetool6 -t Plasma/Applet --install plasmoid ``` or globally with ```bash git clone https://github.com/m-pilia/plasma-applet-ambientnoise cd plasma-applet-ambientnoise/ -cmake . -DCMAKE_INSTALL_PREFIX=`kf5-config --prefix` -make -sudo make install +mkdir build +cmake . -B build +cmake --build build +sudo cmake --install build ``` To see the plasmoid, you may need to restart plasmashell ```bash -kquitapp5 plasmashell -kstart5 plasmashell +kquitapp6 plasmashell +kstart plasmashell ``` # Contribute @@ -71,12 +72,7 @@ In case something seems not to be working, launch the plasmoid in debug mode from a console, with `plasmoidviewer -a org.kde.plasma.ambientnoise` or `plasmawindowed org.kde.plasma.ambientnoise`, and look for relevant log messages. Especially when it comes to audio playback, most of the troubles come -from bad configuration of the multimedia back-end, or missing plugins. - -If no audio is played, or the audio plays but the volume controls do not work, -or if you see messages like `Error: "The autoaudiosink element is missing."` or -`Warning: "No volume control found"`, try installing -[gst-plugins-good](https://gstreamer.freedesktop.org/modules/gst-plugins-good.html). +from bad configuration of the multimedia back-end. # License The project is licensed under GPL 3. See [LICENSE](./LICENSE) diff --git a/icons/CMakeLists.txt b/icons/CMakeLists.txt index 7255551..2cb1522 100755 --- a/icons/CMakeLists.txt +++ b/icons/CMakeLists.txt @@ -1,3 +1,3 @@ -install( DIRECTORY breeze DESTINATION ${ICON_INSTALL_DIR}) -install( DIRECTORY breeze-dark DESTINATION ${ICON_INSTALL_DIR}) -install( DIRECTORY hicolor DESTINATION ${ICON_INSTALL_DIR}) +install(DIRECTORY breeze DESTINATION ${KDE_INSTALL_ICONDIR}) +install(DIRECTORY breeze-dark DESTINATION ${KDE_INSTALL_ICONDIR}) +install(DIRECTORY hicolor DESTINATION ${KDE_INSTALL_ICONDIR}) diff --git a/plasmoid/contents/config/config.qml b/plasmoid/contents/config/config.qml index bb039dc..fa79fb5 100644 --- a/plasmoid/contents/config/config.qml +++ b/plasmoid/contents/config/config.qml @@ -16,8 +16,8 @@ * along with Ambient Noise. If not, see . */ -import QtQuick 2.2 -import org.kde.plasma.configuration 2.0 +import QtQuick +import org.kde.plasma.configuration ConfigModel { ConfigCategory { diff --git a/plasmoid/contents/js/scripts.js b/plasmoid/contents/js/scripts.js index 75e2e40..3b53044 100644 --- a/plasmoid/contents/js/scripts.js +++ b/plasmoid/contents/js/scripts.js @@ -83,7 +83,7 @@ function toImageName(filename) { */ function dataDirectory() { var dir = plasmoid.configuration.noiseDataDirectory; - return dir.trim().replace(/\/*$/, "") + "/"; + return "file://" + dir.trim().replace(/\/*$/, "") + "/"; } /*! @@ -91,11 +91,8 @@ function dataDirectory() { * Multiply it by the global volume, and apply nonlinear scaling. */ function computeVolume(componentVolume) { - var volume = componentVolume * plasmoid.configuration.globalVolume; - volume /= main.maxVolume * main.maxVolume; - return QtMultimedia.convertVolume(volume, - QtMultimedia.LogarithmicVolumeScale, - QtMultimedia.LinearVolumeScale); + const volume = (componentVolume * plasmoid.configuration.globalVolume) / (main.maxVolume ** 2); + return (volume > 0.99) ? 1.0 : -Math.log(1.0 - volume) / Math.log(100.0); } /*! @@ -133,15 +130,11 @@ function saveComponents() { * Restore noise components from settings. */ function restoreComponents() { - deserialiseDataModel(plasmoid.configuration.noiseComponents, noiseComponentsModel); -} - -/*! - * Set the playpause action in the context menu. - */ -function setPlayPauseAction() { - var text = main.playing ? i18n("Pause") : i18n("Play"); - var icon = "media-playback-" + (main.playing ? "pause" : "start"); - plasmoid.removeAction("playpause"); - plasmoid.setAction("playpause", text, icon); + try { + deserialiseDataModel(plasmoid.configuration.noiseComponents, noiseComponentsModel); + } + catch (e) { + console.log(e); + plasmoid.configuration.noiseComponents = "[]"; + } } diff --git a/plasmoid/contents/ui/AddNoisePopup.qml b/plasmoid/contents/ui/AddNoisePopup.qml index c47754b..947b5fe 100644 --- a/plasmoid/contents/ui/AddNoisePopup.qml +++ b/plasmoid/contents/ui/AddNoisePopup.qml @@ -16,19 +16,23 @@ * along with Ambient Noise. If not, see . */ -import QtQuick 2.0 -import QtQuick.Layouts 1.3 -import QtQuick.Controls 1.4 -import QtQuick.Window 2.0 -import Qt.labs.folderlistmodel 1.0 -import org.kde.plasma.components 2.0 as PlasmaComponents -import org.kde.plasma.plasmoid 2.0 +import Qt.labs.folderlistmodel +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window + +import org.kde.kirigami as Kirigami +import org.kde.plasma.components as PlasmaComponents +import org.kde.plasma.extras as PlasmaExtras +import org.kde.plasma.plasmoid + import "../js/scripts.js" as Js ScrollView { ListView { header: PlasmaComponents.ToolButton { - iconName: "draw-arrow-back" + icon.name: "draw-arrow-back" Layout.alignment: Qt.AlignVCenter onClicked: { stack.pop(); @@ -42,28 +46,15 @@ ScrollView { showDirs: false } - delegate: PlasmaComponents.ListItem { - separatorVisible: true - - RowLayout { - - Image { - source: Js.toImageName(fileName) - fillMode: Image.PreserveAspectFit - Layout.preferredHeight: units.iconSizes.medium - Layout.preferredWidth: units.iconSizes.medium - Layout.alignment: Qt.AlignVCenter - } - - PlasmaComponents.Label { - id: fileText - text: Js.toPrettyName(fileName) - Layout.alignment: Qt.AlignVCenter - } - } + delegate: PlasmaExtras.ListItem { + width: row_layout.width + height: row_layout.height + separatorVisible: false MouseArea { - anchors.fill: parent + width: childrenRect.width + height: childrenRect.height + acceptedButtons: Qt.LeftButton onClicked: { noiseComponentsModel.append({ @@ -76,6 +67,24 @@ ScrollView { } stack.pop(); } + + RowLayout { + id: row_layout + + Image { + source: Js.toImageName(fileName) + fillMode: Image.PreserveAspectFit + Layout.preferredHeight: Kirigami.Units.iconSizes.medium + Layout.preferredWidth: Kirigami.Units.iconSizes.medium + Layout.alignment: Qt.AlignVCenter + } + + PlasmaComponents.Label { + id: fileText + text: Js.toPrettyName(fileName) + Layout.alignment: Qt.AlignVCenter + } + } } } } diff --git a/plasmoid/contents/ui/NoiseListItem.qml b/plasmoid/contents/ui/NoiseListItem.qml index 49ec476..ffd6882 100644 --- a/plasmoid/contents/ui/NoiseListItem.qml +++ b/plasmoid/contents/ui/NoiseListItem.qml @@ -16,40 +16,33 @@ * along with Ambient Noise. If not, see . */ -import QtQuick 2.7 -import QtQuick.Layouts 1.3 -import QtQuick.Controls 1.4 -import QtMultimedia 5.7 -import org.kde.plasma.components 2.0 as PlasmaComponents +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import org.kde.kirigami as Kirigami +import org.kde.plasma.components as PlasmaComponents +import org.kde.plasma.extras as PlasmaExtras + import "../js/scripts.js" as Js -PlasmaComponents.ListItem { +PlasmaExtras.ListItem { id: root width: .95 * noiseComponents.width - height: units.gridUnit * 4 - separatorVisible: true + height: Kirigami.Units.gridUnit * 4 + separatorVisible: false property alias noiseName: name.text - property alias audioSource: player.source property alias imageSource: componentIcon.source property alias volume: slider.value property bool muted: false - property bool playing: false - - onPlayingChanged: { - if (playing) { - player.play(); - } else { - player.pause(); - } - } Component.onCompleted: Js.saveComponents() RowLayout { id: componentLine width: root.width - spacing: units.smallSpacing + spacing: Kirigami.Units.smallSpacing // Image for the noise component Image { @@ -73,13 +66,13 @@ PlasmaComponents.ListItem { RowLayout { id: controlsRow width: leftColumn.width - spacing: units.smallSpacing + spacing: Kirigami.Units.smallSpacing Layout.alignment: Qt.AlignCenter // Delete component PlasmaComponents.ToolButton { id: deleteButton - iconName: "edit-delete" + icon.name: "edit-delete" Layout.alignment: Qt.AlignVCenter onClicked: { noiseComponentsModel.remove(index); @@ -90,7 +83,7 @@ PlasmaComponents.ListItem { // Mute component PlasmaComponents.ToolButton { id: muteButton - iconName: Js.volumeIcon(slider.value, muted) + icon.name: Js.volumeIcon(slider.value, muted) Layout.alignment: Qt.AlignVCenter onClicked: { muted = !muted; @@ -104,8 +97,8 @@ PlasmaComponents.ListItem { id: slider Layout.alignment: Qt.AlignVCenter Layout.fillWidth: true - maximumValue: main.maxVolume - minimumValue: main.minVolume + from: main.minVolume + to: main.maxVolume stepSize: main.volumeStep enabled: !muted opacity: muted ? 0.5 : 1.0 @@ -125,11 +118,4 @@ PlasmaComponents.ListItem { } } } - - Audio { - id: player - loops: Audio.Infinite - volume: Js.computeVolume(slider.value * slider.enabled) - autoPlay: root.playing - } } diff --git a/plasmoid/contents/ui/main.qml b/plasmoid/contents/ui/main.qml index 7fe5a18..5054ff3 100644 --- a/plasmoid/contents/ui/main.qml +++ b/plasmoid/contents/ui/main.qml @@ -16,27 +16,31 @@ * along with Ambient Noise. If not, see . */ -import QtQuick 2.0 -import QtQuick.Layouts 1.3 -import QtQuick.Controls 2.2 -import org.kde.plasma.core 2.0 as PlasmaCore -import org.kde.plasma.components 2.0 as PlasmaComponents -import org.kde.plasma.plasmoid 2.0 +import QtMultimedia +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import org.kde.kirigami as Kirigami +import org.kde.plasma.components as PlasmaComponents +import org.kde.plasma.core as PlasmaCore +import org.kde.plasma.plasmoid + import "../js/scripts.js" as Js -Item { +PlasmoidItem { id: main - Layout.minimumHeight: units.gridUnit * 12 - Layout.minimumWidth: units.gridUnit * 12 - Layout.preferredHeight: units.gridUnit * 20 - Layout.preferredWidth: units.gridUnit * 20 + Layout.minimumHeight: Kirigami.Units.gridUnit * 12 + Layout.minimumWidth: Kirigami.Units.gridUnit * 12 + Layout.preferredHeight: Kirigami.Units.gridUnit * 20 + Layout.preferredWidth: Kirigami.Units.gridUnit * 20 - Plasmoid.switchWidth: units.gridUnit * 12 - Plasmoid.switchHeight: units.gridUnit * 12 + switchWidth: Kirigami.Units.gridUnit * 12 + switchHeight: Kirigami.Units.gridUnit * 12 - Plasmoid.toolTipMainText: i18n("Volume") + ": " + plasmoid.configuration.globalVolume + " %" - Plasmoid.toolTipSubText: playing ? i18np("Playing 1 noise", "Playing %1 noises", noiseComponentsModel.count) : i18n("Paused") + toolTipMainText: i18n("Volume") + ": " + plasmoid.configuration.globalVolume + " %" + toolTipSubText: playing ? i18np("Playing 1 noise", "Playing %1 noises", noiseComponentsModel.count) : i18n("Paused") Plasmoid.icon: "ambientnoise" @@ -46,21 +50,60 @@ Item { property bool playing: plasmoid.configuration.playing // Do not bind this to pausedAtStartup + Plasmoid.contextualActions: [ + PlasmaCore.Action { + text: i18n("Play") + icon.name: "media-playback-start" + priority: Plasmoid.LowPriorityAction + visible: !playing + enabled: !playing + onTriggered: action_playpause() + }, + PlasmaCore.Action { + text: i18n("Pause") + icon.name: "media-playback-pause" + priority: Plasmoid.LowPriorityAction + visible: playing + enabled: playing + onTriggered: action_playpause() + } + ] + ListModel { id: noiseComponentsModel + Component.onCompleted: Js.restoreComponents() + } + + ListView { + id: players + model: noiseComponentsModel - Component.onCompleted: { - // Restore noise components - try { - Js.restoreComponents(); + // Nonzero size to allow fitting more than one element + width: 1 + height: 1 - // Force initialisation of the noiseComponents ListView - plasmoid.expanded = true; - plasmoid.expanded = false; + delegate: Item { + id: player_delegate + readonly property real volume: _volume + readonly property bool muted: _muted + readonly property bool playing: main.playing + + onPlayingChanged: { + if (playing) { + media_player.play(); + } + else { + media_player.pause(); + } } - catch (e) { - console.log(e); - plasmoid.configuration.noiseComponents = '[]'; + + MediaPlayer { + id: media_player + source: Js.toAudioName(_filename) + audioOutput: AudioOutput { + volume: Js.computeVolume(!player_delegate.muted * player_delegate.volume) + } + loops: MediaPlayer.Infinite } } } @@ -68,15 +111,15 @@ Item { function action_playpause() { playing = !playing; plasmoid.configuration.playing = playing; - Js.setPlayPauseAction(); } Component.onCompleted: { playing = playing && !plasmoid.configuration.pausedAtStartup; - Js.setPlayPauseAction(); } - Plasmoid.compactRepresentation: PlasmaCore.IconItem { + compactRepresentation: Kirigami.Icon { + property PlasmoidItem plasmoidItem + source: plasmoid.icon active: mouseArea.containsMouse @@ -87,16 +130,16 @@ Item { hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.MiddleButton - onClicked: { + onClicked: function (mouse) { if (mouse.button == Qt.MiddleButton) { action_playpause(); } else if (mouse.button == Qt.LeftButton) { - plasmoid.expanded = !plasmoid.expanded; + plasmoidItem.expanded = !plasmoidItem.expanded; } } - onWheel: { - var angleStep = 15; // As in most mouse types + onWheel: function (wheel) { + var angleStep = 45; var volumeDelta = main.volumeStep * Math.round(wheel.angleDelta.y / angleStep); var volume = plasmoid.configuration.globalVolume + volumeDelta; plasmoid.configuration.globalVolume = Math.min(main.maxVolume, Math.max(main.minVolume, volume)) @@ -104,7 +147,7 @@ Item { } } - Plasmoid.fullRepresentation: StackView { + fullRepresentation: StackView { id: stack initialItem: ColumnLayout { // Global controls @@ -112,13 +155,14 @@ Item { id: globalControls Layout.fillWidth: true - spacing: units.smallSpacing + spacing: Kirigami.Units.smallSpacing // Add new noise component PlasmaComponents.ToolButton { id: addButton - iconName: "list-add" - tooltip: i18n("Add a noise component") + icon.name: "list-add" + ToolTip.text: i18n("Add a noise component") + ToolTip.visible: hovered Layout.alignment: Qt.AlignVCenter onClicked: { stack.push("AddNoisePopup.qml"); @@ -128,7 +172,7 @@ Item { // Play/Pause PlasmaComponents.ToolButton { id: playButton - iconName: playing ? "media-playback-pause" : "media-playback-start" + icon.name: playing ? "media-playback-pause" : "media-playback-start" Layout.alignment: Qt.AlignVCenter onClicked: { action_playpause(); @@ -140,8 +184,8 @@ Item { id: globalVolumeSlider Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter - maximumValue: main.maxVolume - minimumValue: main.minVolume + from: main.minVolume + to: main.maxVolume stepSize: main.volumeStep value: plasmoid.configuration.globalVolume onValueChanged: { @@ -167,8 +211,6 @@ Item { model: noiseComponentsModel delegate: NoiseListItem { - playing: main.playing - audioSource: Js.toAudioName(_filename) imageSource: Js.toImageName(_filename) noiseName: Js.toPrettyName(_filename) volume: _volume diff --git a/plasmoid/contents/ui/settings.qml b/plasmoid/contents/ui/settings.qml index 87eba5a..0c08e00 100755 --- a/plasmoid/contents/ui/settings.qml +++ b/plasmoid/contents/ui/settings.qml @@ -16,12 +16,12 @@ * along with Ambient Noise. If not, see . */ -import QtQuick 2.7 -import QtQuick.Layouts 1.3 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 -import org.kde.plasma.plasmoid 2.0 -import org.kde.plasma.components 2.0 as PlasmaComponents +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +import org.kde.plasma.plasmoid +import org.kde.plasma.components as PlasmaComponents Item { id: settings @@ -49,8 +49,9 @@ Item { /* restore default */ PlasmaComponents.Button { - iconName: "edit-undo" - tooltip: i18n("Restore default") + icon.name: "edit-undo" + ToolTip.text: i18n("Restore default") + ToolTip.visible: hovered onClicked: { noiseData.text = defaultNoiseDataDirectory } diff --git a/plasmoid/metadata.desktop b/plasmoid/metadata.desktop deleted file mode 100644 index 39cfe95..0000000 --- a/plasmoid/metadata.desktop +++ /dev/null @@ -1,23 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Name=Ambient noise -Name[it]=Rumore ambientale -Name[sv]=Omgivande ljud -Comment=Plasmoid for ambient noise reproduction -Comment[it]=Plasmoide per la riproduzione di rumore ambientale -Comment[sv]=Plasmoid som spelar omgivande ljud -Icon=ambientnoise -Type=Service - -X-KDE-PluginInfo-Author=Martino Pilia -X-KDE-PluginInfo-Email=martino.pilia@gmail.com -X-KDE-PluginInfo-Website=https://github.com/m-pilia/plasma-applet-ambientnoise -X-KDE-PluginInfo-License=GPL -X-KDE-PluginInfo-Name=org.kde.plasma.ambientnoise -X-KDE-PluginInfo-Version=0.5 -X-KDE-PluginInfo-EnabledByDefault=true -X-KDE-ServiceTypes=Plasma/Applet -X-Plasma-API=declarativeappletscript -X-Plasma-MainScript=ui/main.qml -X-KDE-PluginInfo-Category=Multimedia -X-Plasma-NotificationArea=true diff --git a/plasmoid/metadata.json b/plasmoid/metadata.json new file mode 100644 index 0000000..87289f9 --- /dev/null +++ b/plasmoid/metadata.json @@ -0,0 +1,30 @@ +{ + "KPackageStructure": "Plasma/Applet", + "KPlugin": { + "Authors": [ + { + "Email": "martino.pilia@gmail.com", + "Name": "Martino Pilia" + } + ], + "Category": "Multimedia", + "Description": "Plasmoid for ambient noise reproduction", + "Description[it]": "Plasmoide per la riproduzione di rumore ambientale", + "Description[sv]": "Plasmoid som spelar omgivande ljud", + "EnabledByDefault": true, + "Icon": "ambientnoise", + "Id": "org.kde.plasma.ambientnoise", + "License": "GPL", + "Name": "Ambient noise", + "Name[it]": "Rumore ambientale", + "Name[sv]": "Omgivande ljud", + "ServiceTypes": [ + "Plasma/Applet" + ], + "Version": "0.6", + "Website": "https://github.com/m-pilia/plasma-applet-ambientnoise" + }, + "X-Plasma-NotificationArea": "true", + "X-Plasma-NotificationAreaCategory": "ApplicationStatus", + "X-Plasma-API-Minimum-Version": "6.0" +}