Skip to content

Replace Qt Multimedia with a native audio abstraction#10098

Draft
i2h3 wants to merge 1 commit into
masterfrom
i2h3/remove-qtmultimedia
Draft

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

Conversation

@i2h3
Copy link
Copy Markdown
Collaborator

@i2h3 i2h3 commented Jun 2, 2026

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
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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
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>
@i2h3 i2h3 force-pushed the i2h3/remove-qtmultimedia branch from 4296d11 to a5243a0 Compare June 3, 2026 12:55
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 3, 2026

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

@i2h3
Copy link
Copy Markdown
Collaborator Author

i2h3 commented Jun 4, 2026

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
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

2 participants