Skip to content

Replace Qt Multimedia with a native audio abstraction#10098

Open
i2h3 wants to merge 2 commits into
masterfrom
i2h3/remove-qtmultimedia
Open

Replace Qt Multimedia with a native audio abstraction#10098
i2h3 wants to merge 2 commits into
masterfrom
i2h3/remove-qtmultimedia

Conversation

@i2h3

@i2h3 i2h3 commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replaces the Qt Multimedia framework — used in exactly one place, to loop the incoming-call ringtone in CallNotificationDialog.qml — with NotificationSoundPlayer, a thin in-tree C++ class that wraps the OS-native audio APIs.

Platform Backend Loop semantics
macOS AVAudioPlayer via Objective-C++ Native (numberOfLoops)
Windows XAudio2 + inline RIFF/fmt/data parser Native (XAUDIO2_BUFFER::LoopCount)
Linux libcanberra (soft build dependency) Per-play, dispatcher-driven

The QML diff is one removed import and one renamed element; ringSound.play() / ringSound.stop() call sites are unchanged. Native-loop backends play the whole sequence and signal finished once; per-play backends signal after each play and the dispatcher re-issues until the loop count is exhausted.

The dispatcher resolves qrc: / file: / plain-path sources, materialising QRC contents into the cache once with an atomic-rename and QTemporaryFile fallback for sandboxed runs.

Two dead Qt5Multimedia*.dll references in the NSIS template are deleted in the same commit (they could never resolve in the current Qt6 build).

Closes #9886

Test plan

  • macOS — Build NextcloudDev locally; confirm the bundle no longer ships QtMultimedia.framework or qml/QtMultimedia/* (verified pre-merge: find Contents -iname '*Multimedia*' returns nothing).
  • macOS — Trigger an incoming Talk call; ringtone plays, Decline stops, 60 s timeout stops, app exit while ringing stops cleanly.
  • Windows — CI build green; trigger an incoming Talk call locally; same matrix.
  • Linux — CI build green with and without libcanberra-dev; on a Pulse host and a Pipewire host: trigger an incoming Talk call; same matrix.
  • Unit testsNotificationSoundPlayerTest passes: covers resolveToFilesystemPath() (QRC extraction + idempotency, file://, plain path, empty, non-existent) and loop bookkeeping (per-play re-issues, native single-fire, stop-mid-sequence cancels).
  • Audio device hotplug — Unplug the output device during playback on each platform; no crash or hang.

🤖 Generated with Claude Code

@i2h3 i2h3 self-assigned this Jun 2, 2026
@i2h3 i2h3 added os: 🍎 macOS Apple macOS, formerly also known as OS X os: 🚪 Windows os: 🐧 Linux labels Jun 2, 2026
@i2h3 i2h3 added this to the 34.0.0 milestone Jun 2, 2026
@github-project-automation github-project-automation Bot moved this to 🧭 Planning evaluation (don't pick) in 💻 Desktop Clients team Jun 2, 2026
@i2h3 i2h3 moved this from 🧭 Planning evaluation (don't pick) to 🏗️ In progress in 💻 Desktop Clients team Jun 2, 2026
@i2h3 i2h3 changed the title feat(audio): replace Qt Multimedia with a native audio abstraction Replace Qt Multimedia with a native audio abstraction Jun 2, 2026
@i2h3 i2h3 requested a review from Copilot June 2, 2026 14:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR removes the Qt Multimedia dependency used only for the incoming-call ringtone by introducing an in-tree NotificationSoundPlayer QML type backed by native OS audio APIs (AVAudioPlayer / XAudio2 / libcanberra-or-noop). This reduces packaging/deployment overhead while preserving the QML call sites (play()/stop()).

Changes:

  • Replace SoundEffect usage in CallNotificationDialog.qml with NotificationSoundPlayer and drop the QtMultimedia import.
  • Add NotificationSoundPlayer implementation + platform backends and register it for QML usage.
  • Wire up build system (platform sources, native link flags, optional libcanberra) and add a unit test + remove dead NSIS Qt5Multimedia DLL lines.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
test/testnotificationsoundplayer.cpp Adds unit tests for QRC resolution and loop bookkeeping.
test/CMakeLists.txt Registers the new NotificationSoundPlayer test target.
src/gui/tray/CallNotificationDialog.qml Switches ringtone element from QtMultimedia SoundEffect to NotificationSoundPlayer.
src/gui/owncloudgui.cpp Registers NotificationSoundPlayer as a QML type.
src/gui/notificationsoundplayer.h Declares the new QML-facing API and backend interface hooks.
src/gui/notificationsoundplayer.cpp Implements dispatcher logic and QRC-to-filesystem extraction caching.
src/gui/notificationsoundplayer_p.h Defines the backend interface and factory function contract.
src/gui/notificationsoundplayer_win.cpp Windows XAudio2 backend + WAV parsing.
src/gui/notificationsoundplayer_mac.mm macOS AVAudioPlayer backend.
src/gui/notificationsoundplayer_linux.cpp Linux libcanberra backend + noop fallback.
src/gui/CMakeLists.txt Adds sources and platform link/defines (AVFoundation/Foundation, xaudio2, optional libcanberra).
cmake/modules/NSIS.template.in Removes stale Qt5Multimedia DLL references from the installer template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/testnotificationsoundplayer.cpp
Comment thread test/testnotificationsoundplayer.cpp
Comment thread test/testnotificationsoundplayer.cpp
Comment thread test/testnotificationsoundplayer.cpp
Comment thread test/testnotificationsoundplayer.cpp
Comment thread src/gui/notificationsoundplayer.cpp Outdated
Comment thread src/gui/notificationsoundplayer.cpp Outdated
Comment thread src/gui/notificationsoundplayer_linux.cpp Outdated
@i2h3 i2h3 force-pushed the i2h3/remove-qtmultimedia branch from 4296d11 to a5243a0 Compare June 3, 2026 12:55
@i2h3

i2h3 commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator Author

Oké, plans might change. Possibly the call notification feature will be removed entirely from the files client due to the Nextcloud Talk desktop client available since the feature release.

@i2h3 i2h3 marked this pull request as draft June 4, 2026 09:33
@i2h3

i2h3 commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator Author

As informed by @Rello, the feature relying on the Qt Multimedia will be retained for now, so this pull request stays valid. I will soon conduct the tests on Windows and Linux.

@i2h3 i2h3 force-pushed the i2h3/remove-qtmultimedia branch from a5243a0 to 5d8c2bb Compare June 9, 2026 08:14
@i2h3 i2h3 marked this pull request as ready for review June 9, 2026 08:14
@i2h3 i2h3 force-pushed the i2h3/remove-qtmultimedia branch 2 times, most recently from 9b9edfa to 0397bd4 Compare June 9, 2026 10:48
class Backend;

explicit NotificationSoundPlayer(QObject *parent = nullptr);
NotificationSoundPlayer(std::unique_ptr<Backend> backend, QObject *parent);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

can you add explicit on the constructor ?

}

if (candidate.startsWith(QStringLiteral(":"))) {
const auto extracted = extractQrcToCache(candidate);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

from what I understand the libcanberra linux backend is playing platform sounds rather than real music files
so that would sound unneeded on linux at all and adding complexity
can we only use this when needed by the backend ?

i2h3 and others added 2 commits June 9, 2026 17:53
The Qt Multimedia framework was pulled into the desktop client solely to
play the call-notification ringtone in a loop via QML's SoundEffect. This
introduces NotificationSoundPlayer, a thin in-tree C++ class that wraps
the OS-native audio APIs (AVAudioPlayer on macOS, XAudio2 on Windows,
libcanberra on Linux) and exposes the same minimal QML API the dialog
needs. Removing the import lets macdeployqt drop the QtMultimedia
framework and QML plugin from the bundle and unblocks shrinking the
Windows installer.

The dispatcher resolves qrc:/file:/plain-path sources, extracts QRC
contents to the cache with an atomic-rename + QTemporaryFile fallback,
and drives loop counting for backends that play one buffer at a time
(Linux). Native-loop backends (macOS, Windows) play the whole sequence
in one shot. Backend choice is platform-gated in CMake; libcanberra is
a soft build dependency on Linux with a no-op fallback.

Also deletes two dead Qt5Multimedia.dll references from the NSIS
template that could never resolve in the current Qt6 build.

Closes #9886

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
… project

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
@i2h3 i2h3 force-pushed the i2h3/remove-qtmultimedia branch from 0397bd4 to ea85a91 Compare June 9, 2026 15:53
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Artifact containing the AppImage: nextcloud-appimage-pr-10098.zip

Digest: sha256:d8804ca2c195ef1128dfffc6658b1451b641a5ac7c788e163939550a54e9b535

To test this change/fix you can download the above artifact file, unzip it, and run it.

Please make sure to quit your existing Nextcloud app and backup your data.

@sonarqubecloud

sonarqubecloud Bot commented Jun 9, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
64.4% Coverage on New Code (required ≥ 80%)
21 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

os: 🍎 macOS Apple macOS, formerly also known as OS X os: 🚪 Windows os: 🐧 Linux

Projects

Status: 🏗️ In progress

Development

Successfully merging this pull request may close these issues.

Replace Qt Multimedia with a native audio abstraction

3 participants