Skip to content

[4.7.0] Audio API section: various fixes#32945

Open
RomanPudashkin wants to merge 2 commits intomusescore:4.7from
RomanPudashkin:audio_api_section_fixes_470
Open

[4.7.0] Audio API section: various fixes#32945
RomanPudashkin wants to merge 2 commits intomusescore:4.7from
RomanPudashkin:audio_api_section_fixes_470

Conversation

@RomanPudashkin
Copy link
Copy Markdown
Contributor

@RomanPudashkin RomanPudashkin commented Apr 8, 2026

Resolves: #31663
Resolves: #31664

Summary by CodeRabbit

  • New Features

    • Interactive warning shown when switching to an audio driver with no output devices; selection reverts to the previous driver when confirmed.
    • Improved UI label: "Audio API" renamed to "Audio driver".
  • Bug Fixes

    • More reliable default audio-device selection during driver initialization.
    • Clarified warning and log messages for driver/device state.
    • Minor performance improvements when enumerating MIDI devices.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 8, 2026

📝 Walkthrough

Walkthrough

Adds logic to resolve ASIO driver device IDs before loading, and adds UI-model validation when switching audio APIs: if the newly selected API has no output devices, an interactive warning is shown and the selection reverts to the previous API.

Changes

Cohort / File(s) Summary
ASIO driver device-id resolution
src/framework/audio/driver/platform/win/asio/asioaudiodriver.cpp
Derive ASIO driver identifier from Spec.deviceId as an AudioDeviceID, replace with defaultDevice() when equal to DEFAULT_DEVICE_ID, and pass the resolved deviceId to driver loading instead of using spec.deviceId.c_str() directly.
Audio driver open control flow & logging
src/framework/audio/main/internal/audiodrivercontroller.cpp
Adjust control flow when opening devices: non-empty spec.deviceId is overwritten to DEFAULT_DEVICE_ID before calling open. Update logging/warning text formatting.
Preferences model: API switch validation & minor optimizations
src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.h, src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.cpp
Add IInteractive context-injected member; when changing audio API, snapshot fallback API, register a one-shot availableOutputDevicesChanged() handler to show an interactive warning and revert to fallback if no outputs are available. Also pre-materialize device lists and reserve capacity in MIDI device methods.
UI text update
src/preferences/qml/MuseScore/Preferences/internal/AudioApiSection.qml
Change displayed ComboBox title from “Audio API” to “Audio driver”.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant Prefs as Preferences UI
    participant Model as AudioMidiPreferencesModel
    participant Controller as AudioDriverController
    participant Driver as AsioAudioDriver
    participant Dialog as Interactive Warning

    User->>Prefs: Select audio API
    Prefs->>Model: setCurrentAudioApiIndex()
    Model->>Model: Save fallback API
    Model->>Model: Register one-shot availableOutputDevicesChanged listener
    Model->>Controller: changeCurrentAudioApi(spec)
    Controller->>Driver: open(spec)
    Driver->>Driver: Resolve deviceId (use defaultDevice() if DEFAULT_DEVICE_ID)
    Driver->>Driver: loadDriver(resolvedDeviceId)
    Controller-->>Model: Driver initialized / opened
    Model->>Model: availableOutputDevicesChanged() triggers

    alt no output devices
        Model->>Dialog: Show interactive warning
        Dialog->>User: Inform & prompt
        User->>Dialog: Confirm
        Model->>Model: Revert to fallback API
        Model->>Prefs: Emit currentAudioApiIndexChanged()
    else devices present
        Model->>Prefs: Complete selection
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Most changes are well-scoped to audio API/device selection, but minor optimizations in midiInputDevices() and midiOutputDevices() (vector reservation and local storage) lack clear justification beyond efficiency. Clarify the rationale for non-functional optimizations in midi device listing methods or consider separating them into a distinct commit/PR if unrelated to the core audio API fixes.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title '[4.7.0] Audio API section: various fixes' accurately describes the primary changes addressing audio API device selection and ASIO handling across multiple files.
Description check ✅ Passed The description includes links to both resolved issues (#31663 and #31664), meeting the core requirement despite lacking additional detail.
Linked Issues check ✅ Passed The code changes address both issue requirements: issue #31663 is resolved by having AsioAudioDriver derive deviceId from Spec and applying default-device logic, while #31664 is addressed by the warning dialog in AudioMidiPreferencesModel when no devices are available.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@RomanPudashkin RomanPudashkin force-pushed the audio_api_section_fixes_470 branch from 033687c to 7b880aa Compare April 8, 2026 09:29
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/framework/audio/main/internal/audiodrivercontroller.cpp (1)

227-235: ⚠️ Potential issue | 🟠 Major

Do not persist unavailable API selection.

Line 234 updates config even when no device exists (Lines 230-232) or open fails, so the UI can still remain on an unavailable API.

💡 Proposed fix
-    if (!spec.deviceId.empty()) {
+    bool opened = false;
+    if (!spec.deviceId.empty()) {
         spec.deviceId = DEFAULT_DEVICE_ID;
-        m_audioDriver->open(spec, nullptr);
+        opened = m_audioDriver->open(spec, nullptr);
     } else {
         LOGW() << "No devices for " << name;
     }
 
-    configuration()->setCurrentAudioApi(name);
+    if (!opened) {
+        LOGW() << "Audio API switch aborted, unavailable device(s) for " << name;
+        return;
+    }
+
+    configuration()->setCurrentAudioApi(name);

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 58d4b731-f8ae-4f06-86a9-1f088ac44117

📥 Commits

Reviewing files that changed from the base of the PR and between a601bfc and 7b880aa.

📒 Files selected for processing (14)
  • src/framework/audio/driver/platform/win/asio/asioaudiodriver.cpp
  • src/framework/audio/main/internal/audiodrivercontroller.cpp
  • src/preferences/CMakeLists.txt
  • src/preferences/internal/preferencesconfiguration.cpp
  • src/preferences/internal/preferencesconfiguration.h
  • src/preferences/ipreferencesconfiguration.h
  • src/preferences/preferencesmodule.cpp
  • src/preferences/preferencesmodule.h
  • src/preferences/qml/MuseScore/Preferences/AudioMidiPreferencesPage.qml
  • src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.cpp
  • src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.h
  • src/preferences/qml/MuseScore/Preferences/internal/AudioApiSection.qml
  • src/preferences/qml/MuseScore/Preferences/internal/ComboBoxWithTitle.qml
  • src/preferences/qml/MuseScore/Preferences/internal/CommonAudioApiConfiguration.qml

@RomanPudashkin RomanPudashkin force-pushed the audio_api_section_fixes_470 branch from 7b880aa to 47132cd Compare April 8, 2026 10:34
@RomanPudashkin RomanPudashkin force-pushed the audio_api_section_fixes_470 branch from 47132cd to 8f49b9b Compare April 8, 2026 10:39
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/preferences/qml/MuseScore/Preferences/internal/AudioApiSection.qml (1)

60-75: ⚠️ Potential issue | 🟠 Major

The warning button approach may not fully address issue #31664.

The button only appears when outputDeviceCount === 0, but users must manually discover and click it to see the warning. Issue #31664 requests that ASIO selection should be prevented or a warning shown proactively when no ASIO device is present.

Consider automatically triggering showNoOutputDevicesWarningRequested() when:

  1. The audio API is changed to one with no available devices, or
  2. The component loads with an API that has no devices

This could be done via a Component.onCompleted check or an onOutputDeviceCountChanged handler that auto-fires the warning under specific conditions (respecting the "don't show again" preference).

src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.cpp (1)

159-172: ⚠️ Potential issue | 🟠 Major

Move the opt-out guard into showNoOutputDevicesWarning() itself.

This method is Q_INVOKABLE and can be called directly from QML (e.g., AudioMidiPreferencesPage.qml) without going through setCurrentAudioApiIndex(). The shouldShowNoOutputDevicesWarning() guard at line 54 only protects the C++ call path, allowing the QML call path to bypass the user's "don't show again" preference.

,

🛡️ Proposed fix to add internal guard
 void AudioMidiPreferencesModel::showNoOutputDevicesWarning()
 {
+    if (!preferencesConfiguration()->shouldShowNoOutputDevicesWarning()) {
+        return;
+    }
+
     auto promise = interactive()->warning(
         muse::trc("preferences", "No output devices available"),

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e7bce1ef-5524-40f2-9b18-7d21620efb91

📥 Commits

Reviewing files that changed from the base of the PR and between 7b880aa and 8f49b9b.

📒 Files selected for processing (12)
  • src/preferences/CMakeLists.txt
  • src/preferences/internal/preferencesconfiguration.cpp
  • src/preferences/internal/preferencesconfiguration.h
  • src/preferences/ipreferencesconfiguration.h
  • src/preferences/preferencesmodule.cpp
  • src/preferences/preferencesmodule.h
  • src/preferences/qml/MuseScore/Preferences/AudioMidiPreferencesPage.qml
  • src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.cpp
  • src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.h
  • src/preferences/qml/MuseScore/Preferences/internal/AudioApiSection.qml
  • src/preferences/qml/MuseScore/Preferences/internal/ComboBoxWithTitle.qml
  • src/preferences/qml/MuseScore/Preferences/internal/CommonAudioApiConfiguration.qml

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a448c34a-bb5f-4717-8ef5-59d6ce5ec6ee

📥 Commits

Reviewing files that changed from the base of the PR and between 8f49b9b and d23ce05.

📒 Files selected for processing (2)
  • src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.cpp
  • src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.h

@RomanPudashkin RomanPudashkin force-pushed the audio_api_section_fixes_470 branch from d23ce05 to f904dbe Compare April 9, 2026 07:04
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.cpp (1)

70-72: ⚠️ Potential issue | 🟡 Minor

Remove the redundant rollback signal emission.

changeCurrentAudioApi(fallbackApi) already triggers currentAudioApiChanged(), and init() forwards that to currentAudioApiIndexChanged() at Lines 134-136. Emitting it again here double-notifies the UI on the rollback path.

♻️ Suggested simplification
         promise.onResolve(this, [this, fallbackApi](const muse::IInteractive::Result&) {
             audioDriverController()->changeCurrentAudioApi(fallbackApi);
-            emit currentAudioApiIndexChanged(currentAudioApiIndex());
         });

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 79bc7be8-7b70-4690-b3cd-73910e68ac61

📥 Commits

Reviewing files that changed from the base of the PR and between d23ce05 and f904dbe.

📒 Files selected for processing (3)
  • src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.cpp
  • src/preferences/qml/MuseScore/Preferences/audiomidipreferencesmodel.h
  • src/preferences/qml/MuseScore/Preferences/internal/AudioApiSection.qml

@bkunda
Copy link
Copy Markdown

bkunda commented Apr 9, 2026

One observation:

  1. Start with default driver (WASAPI) with no connected ASIO device
  2. Select Audio driver > ASIO: warning dialog is triggered (expected)
  3. Click OK in warning dialog: Audio driver resets to WASAPI (expected)
  4. Switch on/connect ASIO device: Windows recognises the device and enables it (expected)
  5. Select Audio driver > ASIO: warning dialog is triggered (not expected: ASIO driver should be enabled since the device is now active)

In this case, the ASIO driver can only be selected after restarting MuseScore Studio.

@bkunda
Copy link
Copy Markdown

bkunda commented Apr 9, 2026

Second observation: When selecting ASIO as the driver, the device field remains empty, even if there's only one available device.

Is it possible to enable an available device as soon as ASIO is selected? If there's only one, enable it. If there's more than one, just pick one :-)

Screen.Recording.2026-04-09.161603.mp4

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

Labels

None yet

Projects

None yet

3 participants