Skip to content

Add ability to rescan all plugins#125

Open
RomanPudashkin wants to merge 10 commits into
musescore:mainfrom
RomanPudashkin:add_ability_to_rescan_all_plugins
Open

Add ability to rescan all plugins#125
RomanPudashkin wants to merge 10 commits into
musescore:mainfrom
RomanPudashkin:add_ability_to_rescan_all_plugins

Conversation

@RomanPudashkin

Copy link
Copy Markdown
Contributor

Ports (changes in the framework): musescore/MuseScore#33855
Also ports: musescore/MuseScore#33848

RomanPudashkin and others added 10 commits July 2, 2026 16:59
Added instruments:
- China: Guqin, Pipa, Yangqin
- Japan: Hichiriki, Sho
- Korea (melodic): Ajaeng, Daegeum, Gayageum
- Korea (percussion): Samul Buk, Samul Janggu, Sanjo Janggu, Sori Buk

Also fix typos in Guzheng and Baryton IDs
* ASIO reset() now fires availableOutputDevicesChanged instead of
  self-handling close/reopen, matching the WASAPI behavior
* AudioDriverController::checkOutputDevice() falls back to the default
  audio driver (WASAPI) if reopen fails
…to_system_default

Fix auto switch to system default
…later

The dock widget may still hold a pointer to such a frame in m_lastPositions
Restoring it there causes FrameQuick::~FrameQuick()
to delete the dock widget via qDeleteAll(), leading to a crash later
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This pull request adds a clear() method to the audio plugins registry interface and implementation, which empties plugin data, persists the change, and notifies listeners. A new rescanAllPlugins() method is added to the register scenario interface and implementation, which clears the registry and then updates it. The test mock is updated to include the new clear() method. Separately, dock window code in both dockwindow and dockwindow_v2 modules now connects to the destroyed signal of custom menu models to nullify stale pointers, and KDDockWidgets' LayoutWidget adds a guard to skip placeholder restoration on frames marked for deletion.

Changes

Cohort / File(s) Summary
Audio plugins registry clear/rescan
iknownaudiopluginsregister.h, internal/knownaudiopluginsregister.cpp, internal/knownaudiopluginsregister.h, iregisteraudiopluginsscenario.h, internal/registeraudiopluginsscenario.h, internal/registeraudiopluginsscenario.cpp, tests/mocks/knownaudiopluginsregistermock.h
Adds clear() to the known plugins registry interface/implementation/mock, and adds rescanAllPlugins() to the register scenario interface/implementation which calls clear() then updatePluginsRegistry().
Dock window pointer/frame guards
dockwindow/qml/Muse/Dock/dockpanelview.cpp, dockwindow_v2/qml/Muse/Dock/dockpanelview.cpp, dockwindow/thirdparty/KDDockWidgets/src/private/LayoutWidget.cpp
Connects to destroyed signal to nullify m_customMenuModel when the custom menu model is deleted; adds early return in restorePlaceholder when the target frame is being deleted.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant RegisterAudioPluginsScenario
  participant KnownAudioPluginsRegister
  Caller->>RegisterAudioPluginsScenario: rescanAllPlugins()
  RegisterAudioPluginsScenario->>KnownAudioPluginsRegister: clear()
  KnownAudioPluginsRegister->>KnownAudioPluginsRegister: empty maps, writePluginsInfo(), notify
  KnownAudioPluginsRegister-->>RegisterAudioPluginsScenario: Ret
  RegisterAudioPluginsScenario->>RegisterAudioPluginsScenario: updatePluginsRegistry()
Loading

Estimated code review effort: 2 (Simple)

Related issues: None provided in context.

Related PRs: None provided in context.

Suggested labels: audioplugins, dockwindow, bugfix

Suggested reviewers: None provided in context.

Poem

A rabbit hopped through registry code,
Clearing old plugins from their abode.
A rescan signal, clean and new,
While dangling pointers bid adieu.
Frames marked for deletion now stand aside—
This burrow of code is tidy inside! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is missing the required template sections, including an issue reference, summary, checklist, and build configuration details. Add the template sections, including a Resolves issue link, a brief motivation/summary, the checklist, and any relevant build/test details.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding the ability to rescan all plugins.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (2)
framework/dockwindow_v2/qml/Muse/Dock/dockpanelview.cpp (1)

82-101: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Same stale-model closure issue as in dockwindow's dockpanelview.cpp.

The destroyed lambda unconditionally nulls m_customMenuModel without checking whether the destroyed object is still the currently-assigned model. If setCustomMenuModel() is called again before the previous model is destroyed, the previous model's destroyed connection survives (bound to this) and can later null out a reference to a newer, still-valid model.

🐛 Proposed fix
-        connect(model, &AbstractMenuModel::destroyed, this, [this]() {
-            m_customMenuModel = nullptr;
-        });
+        connect(model, &AbstractMenuModel::destroyed, this, [this, model]() {
+            if (m_customMenuModel == model) {
+                m_customMenuModel = nullptr;
+            }
+        });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/dockwindow_v2/qml/Muse/Dock/dockpanelview.cpp` around lines 82 -
101, The stale-model reset in setCustomMenuModel is unsafe because the destroyed
handler can clear m_customMenuModel even after a newer model has been assigned.
Update the destroyed connection in dockpanelview.cpp so it only nulls
m_customMenuModel when the destroyed object matches the currently stored model,
using the setCustomMenuModel lambda and the AbstractMenuModel pointer captured
there to guard against overwriting a newer model.
framework/dockwindow/qml/Muse/Dock/dockpanelview.cpp (1)

80-99: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Stale-model closure can null out a newer, still-valid m_customMenuModel.

The destroyed lambda captures no reference to model, so it unconditionally clears m_customMenuModel. If setCustomMenuModel() is called again with a new model before the old one is destroyed, the old model's destroyed connection is never removed (it lives as long as this). When the old model is eventually destroyed, this stale connection fires and wipes out the pointer to the current, still-valid model — silently dropping custom context-menu items even though the new model is alive.

🐛 Proposed fix: only clear if the destroyed model is still the current one
-        connect(model, &AbstractMenuModel::destroyed, this, [this]() {
-            m_customMenuModel = nullptr;
-        });
+        connect(model, &AbstractMenuModel::destroyed, this, [this, model]() {
+            if (m_customMenuModel == model) {
+                m_customMenuModel = nullptr;
+            }
+        });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/dockwindow/qml/Muse/Dock/dockpanelview.cpp` around lines 80 - 99,
The destroyed-handler in setCustomMenuModel() can clear a newer model by
accident, because it unconditionally resets m_customMenuModel when any
previously connected AbstractMenuModel is destroyed. Update the lambda connected
to AbstractMenuModel::destroyed so it identifies the specific model instance it
was created for and only sets m_customMenuModel to nullptr if that destroyed
instance is still the current m_customMenuModel; keep the existing itemsChanged
and itemChanged connections in setCustomMenuModel() unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@framework/audioplugins/internal/knownaudiopluginsregister.cpp`:
- Around line 156-165: The clear() logic in KnownAudioPluginsRegister is wiping
all AudioPluginInfo state, so rescanAllPlugins() recreates plugins with default
values and loses persisted enabled/errorCode settings. Update clear() so it
preserves existing plugin metadata across rescans, and only refresh the plugin
inventory/paths as needed; use KnownAudioPluginsRegister::clear and
rescanAllPlugins as the main places to keep disabled status and stored errorCode
intact when rebuilding the list.

---

Outside diff comments:
In `@framework/dockwindow_v2/qml/Muse/Dock/dockpanelview.cpp`:
- Around line 82-101: The stale-model reset in setCustomMenuModel is unsafe
because the destroyed handler can clear m_customMenuModel even after a newer
model has been assigned. Update the destroyed connection in dockpanelview.cpp so
it only nulls m_customMenuModel when the destroyed object matches the currently
stored model, using the setCustomMenuModel lambda and the AbstractMenuModel
pointer captured there to guard against overwriting a newer model.

In `@framework/dockwindow/qml/Muse/Dock/dockpanelview.cpp`:
- Around line 80-99: The destroyed-handler in setCustomMenuModel() can clear a
newer model by accident, because it unconditionally resets m_customMenuModel
when any previously connected AbstractMenuModel is destroyed. Update the lambda
connected to AbstractMenuModel::destroyed so it identifies the specific model
instance it was created for and only sets m_customMenuModel to nullptr if that
destroyed instance is still the current m_customMenuModel; keep the existing
itemsChanged and itemChanged connections in setCustomMenuModel() unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8bc5de1f-7d99-4dfa-bfed-a939542cfce0

📥 Commits

Reviewing files that changed from the base of the PR and between 9abcdbc and 7dfa76d.

📒 Files selected for processing (10)
  • framework/audioplugins/iknownaudiopluginsregister.h
  • framework/audioplugins/internal/knownaudiopluginsregister.cpp
  • framework/audioplugins/internal/knownaudiopluginsregister.h
  • framework/audioplugins/internal/registeraudiopluginsscenario.cpp
  • framework/audioplugins/internal/registeraudiopluginsscenario.h
  • framework/audioplugins/iregisteraudiopluginsscenario.h
  • framework/audioplugins/tests/mocks/knownaudiopluginsregistermock.h
  • framework/dockwindow/qml/Muse/Dock/dockpanelview.cpp
  • framework/dockwindow/thirdparty/KDDockWidgets/src/private/LayoutWidget.cpp
  • framework/dockwindow_v2/qml/Muse/Dock/dockpanelview.cpp

Comment on lines +156 to +165
Ret KnownAudioPluginsRegister::clear()
{
m_pluginInfoMap.clear();
m_pluginPaths.clear();

Ret ret = writePluginsInfo();
m_pluginInfoListChanged.notify();

return ret;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect registerNewPlugins/registerPlugin to see default enabled/errorCode handling
rg -n -B2 -A20 'Ret RegisterAudioPluginsScenario::registerNewPlugins|Ret RegisterAudioPluginsScenario::registerPlugin\(' framework/audioplugins/internal/registeraudiopluginsscenario.cpp

Repository: musescore/muse_framework

Length of output: 1438


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the registration path and persistence handling around plugin state.
sed -n '150,280p' framework/audioplugins/internal/registeraudiopluginsscenario.cpp
printf '\n====\n'
sed -n '240,340p' framework/audioplugins/internal/knownaudiopluginsregister.cpp
printf '\n====\n'
rg -n 'enabled|errorCode|AudioPluginInfo' framework/audioplugins/internal/registeraudiopluginsscenario.cpp framework/audioplugins/internal/knownaudiopluginsregister.cpp

Repository: musescore/muse_framework

Length of output: 6160


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '120,240p' framework/audioplugins/internal/knownaudiopluginsregister.cpp
printf '\n====\n'
sed -n '1,140p' framework/audioplugins/internal/registeraudiopluginsscenario.cpp
printf '\n====\n'
rg -n 'rescanAllPlugins|updatePluginsRegistry|clear\(\)' framework/audioplugins/internal/*.cpp framework/audioplugins/internal/*.h

Repository: musescore/muse_framework

Length of output: 8328


Rescan preserves no plugin state
clear() drops every AudioPluginInfo, so rescanAllPlugins() rebuilds entries with fresh defaults (enabled = true for newly registered plugins). That can silently re-enable disabled plugins and erase stored errorCode values.

🧰 Tools
🪛 Clang (14.0.6)

[warning] 156-156: use a trailing return type for this function

(modernize-use-trailing-return-type)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/audioplugins/internal/knownaudiopluginsregister.cpp` around lines
156 - 165, The clear() logic in KnownAudioPluginsRegister is wiping all
AudioPluginInfo state, so rescanAllPlugins() recreates plugins with default
values and loses persisted enabled/errorCode settings. Update clear() so it
preserves existing plugin metadata across rescans, and only refresh the plugin
inventory/paths as needed; use KnownAudioPluginsRegister::clear and
rescanAllPlugins as the main places to keep disabled status and stored errorCode
intact when rebuilding the list.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant