Skip to content

Commit 10f2c9d

Browse files
committed
Fix subwindow logic safety, FX Mute stuck on UI lock, and Slot 1 Music not refreshing after unlock
1 parent b78c088 commit 10f2c9d

13 files changed

+111
-33
lines changed

Source/GUI/Components/FxSendsComponent.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include "../../GUI/Layout/TrackComponent.h"
33
#include "../../Components/Helpers.h"
44

5-
// ================== Component Tiêu Đề Tùy Chỉnh ==================
5+
// ... (FxSendsTitleComponent class is unchanged) ...
66
class FxSendsTitleComponent : public juce::Component
77
{
88
public:
@@ -121,4 +121,20 @@ void FxSendsComponent::updateTexts()
121121
{
122122
updateMuteButtonState(i, fxMuteButtons[i].getToggleState());
123123
}
124+
}
125+
126+
// <<< ADDED: Implementation of the new granular locking function >>>
127+
void FxSendsComponent::setLocked(bool shouldBeLocked)
128+
{
129+
// Only disable the buttons that open FX windows
130+
for (auto& button : fxButtons)
131+
{
132+
button.setEnabled(!shouldBeLocked);
133+
}
134+
135+
// The mute buttons are NEVER locked
136+
for (auto& muteButton : fxMuteButtons)
137+
{
138+
muteButton.setEnabled(true);
139+
}
124140
}

Source/GUI/Components/FxSendsComponent.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class FxSendsComponent : public juce::Component,
2020

2121
void updateMuteButtonState(int index, bool isMuted);
2222

23+
// <<< ADDED: New method to handle granular locking >>>
24+
void setLocked(bool shouldBeLocked);
25+
2326
private:
2427
void changeListenerCallback(juce::ChangeBroadcaster* source) override;
2528
void updateTexts();

Source/GUI/Components/ProjectManagerComponent.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,7 @@ ProjectManagerComponent::ProjectManagerComponent(AudioEngine& engine) : audioEng
4949

5050
ProjectManagerComponent::~ProjectManagerComponent()
5151
{
52-
if (projectListWindow != nullptr)
53-
{
54-
delete projectListWindow.getComponent();
55-
}
52+
// unique_ptr will handle deletion automatically.
5653
LanguageManager::getInstance().removeChangeListener(this);
5754
audioEngine.getProjectState().removeListener(this);
5855
}
@@ -197,15 +194,21 @@ void ProjectManagerComponent::stopProject()
197194
audioEngine.stopLoadedProject();
198195
}
199196

197+
// <<< MODIFIED: Now uses unique_ptr and a callback for lifecycle management >>>
200198
void ProjectManagerComponent::manageProjects()
201199
{
202200
if (projectListWindow == nullptr)
203201
{
204-
auto* window = new ProjectListWindow("Projects", audioEngine, [this](const juce::File& projectJsonFile) {
205-
audioEngine.loadProject(projectJsonFile);
206-
});
207-
projectListWindow = window;
208-
window->setVisible(true);
202+
projectListWindow = std::make_unique<ProjectListWindow>(
203+
"Projects",
204+
audioEngine,
205+
[this](const juce::File& projectJsonFile) {
206+
audioEngine.loadProject(projectJsonFile);
207+
},
208+
[this] { // on close callback
209+
projectListWindow.reset();
210+
}
211+
);
209212
}
210213
else
211214
{

Source/GUI/Components/ProjectManagerComponent.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class ProjectManagerComponent : public juce::Component,
2929

3030
AudioEngine& audioEngine;
3131

32-
// <<< SỬA: Thay thế WeakReference bằng Component::SafePointer >>>
33-
juce::Component::SafePointer<ProjectListWindow> projectListWindow;
32+
// <<< MODIFIED: Changed from SafePointer to unique_ptr for ownership >>>
33+
std::unique_ptr<ProjectListWindow> projectListWindow;
3434

3535
juce::Label loadedProjectTitleLabel;
3636
juce::Label loadedProjectLabel;

Source/GUI/Layout/MasterUtilityComponent.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,20 @@ MasterUtilityComponent::MasterUtilityComponent(AudioEngine& engine)
4444
}
4545
};
4646

47-
quickKeySettingsButton.onClick = []
47+
// <<< MODIFIED: This now safely manages the window's lifecycle >>>
48+
quickKeySettingsButton.onClick = [this]
4849
{
49-
// new QuickKeySettingsWindow(); // This creates a memory leak, will need fixing later
50+
if (quickKeySettingsWindow == nullptr)
51+
{
52+
// Create the window with a callback that resets this unique_ptr
53+
quickKeySettingsWindow = std::make_unique<QuickKeySettingsWindow>(
54+
[this] { quickKeySettingsWindow.reset(); }
55+
);
56+
}
57+
else
58+
{
59+
quickKeySettingsWindow->toFront(true);
60+
}
5061
};
5162

5263
addAndMakeVisible(masterVolumeLabel);
@@ -201,6 +212,11 @@ void MasterUtilityComponent::closeAllPluginWindows()
201212
{
202213
masterPluginsWindow.reset();
203214
}
215+
// <<< ADDED: Also close the QuickKeySettingsWindow on shutdown >>>
216+
if (quickKeySettingsWindow != nullptr)
217+
{
218+
quickKeySettingsWindow.reset();
219+
}
204220
}
205221

206222
void MasterUtilityComponent::updateLockState()

Source/GUI/Layout/MasterUtilityComponent.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include "../../GUI/Components/RecorderComponent.h"
1313

1414
class MasterPluginsWindow;
15+
// <<< ADDED: Forward declaration for QuickKeySettingsWindow >>>
16+
class QuickKeySettingsWindow;
1517

1618
class MasterUtilityComponent : public juce::Component,
1719
public juce::ChangeListener
@@ -47,6 +49,8 @@ class MasterUtilityComponent : public juce::Component,
4749
MasterProcessor* masterProcessor = nullptr;
4850

4951
std::unique_ptr<MasterPluginsWindow> masterPluginsWindow;
52+
// <<< ADDED: std::unique_ptr to own the settings window >>>
53+
std::unique_ptr<QuickKeySettingsWindow> quickKeySettingsWindow;
5054

5155
// <<< THÊM COMPONENT MỚI >>>
5256
std::unique_ptr<RecorderComponent> recorderComponent;

Source/GUI/Layout/TrackComponent.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,29 @@ class TrackComponent::PluginItemComponent : public juce::Component,
154154

155155
void setLocked(bool shouldBeLocked, bool isSpecialSlot)
156156
{
157-
if (isSpecialSlot && shouldBeLocked)
157+
if (!isSpecialSlot)
158+
{
159+
setEnabled(!shouldBeLocked);
160+
return;
161+
}
162+
163+
if (shouldBeLocked)
158164
{
159165
setEnabled(true);
160166
openButton.setEnabled(true);
161-
162167
powerButton.setEnabled(false);
163168
removeButton.setEnabled(false);
164169
moveUpButton.setEnabled(false);
165170
moveDownButton.setEnabled(false);
166171
}
167172
else
168173
{
169-
setEnabled(!shouldBeLocked);
174+
setEnabled(true);
175+
openButton.setEnabled(true);
176+
powerButton.setEnabled(true);
177+
removeButton.setEnabled(true);
178+
moveUpButton.setEnabled(true);
179+
moveDownButton.setEnabled(true);
170180
}
171181
}
172182
private:
@@ -909,8 +919,10 @@ void TrackComponent::updateLockState()
909919
volumeSlider.setEnabled(!isLocked);
910920
addPluginSelector.setEnabled(!isLocked);
911921
addButton.setEnabled(!isLocked);
912-
fxSends->setEnabled(!isLocked);
913-
muteButton.setEnabled(true);
922+
923+
fxSends->setLocked(isLocked);
924+
925+
muteButton.setEnabled(true); // Mute button is always enabled
914926

915927
pluginListBox.setEnabled(true);
916928

Source/GUI/Windows/FXChainWindow.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,13 @@ FXChainWindow::FXChainWindow(const juce::String& name, ProcessorBase& processorT
422422

423423
FXChainWindow::~FXChainWindow() { contentComponent.reset(); }
424424

425+
// <<< MODIFIED: Safe self-deletion >>>
425426
void FXChainWindow::closeButtonPressed()
426427
{
427-
delete this;
428+
// This safely schedules the deletion of this window on the message thread,
429+
// preventing crashes if the window is still being accessed.
430+
juce::MessageManager::callAsync([safeThis = juce::Component::SafePointer(this)]() mutable {
431+
if (safeThis)
432+
delete safeThis.getComponent();
433+
});
428434
}

Source/GUI/Windows/PluginEditorWindow.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,13 @@ class PluginEditorWindow : public juce::DocumentWindow,
119119

120120
juce::AudioPluginInstance& getOwnerPlugin() const { return ownerPlugin; }
121121

122+
// <<< MODIFIED: Safe self-deletion >>>
122123
void closeButtonPressed() override
123124
{
124-
juce::MessageManager::callAsync([this] { delete this; });
125+
juce::MessageManager::callAsync([safeThis = juce::Component::SafePointer(this)]() mutable {
126+
if (safeThis)
127+
delete safeThis.getComponent();
128+
});
125129
}
126130

127131
void audioProcessorParameterChanged(juce::AudioProcessor*, int, float) override {}

Source/GUI/Windows/ProjectListWindow.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,12 @@ class ProjectListContentComponent : public juce::Component,
156156
// <<< SỬA: Cập nhật hàm khởi tạo của Window >>>
157157
ProjectListWindow::ProjectListWindow(const juce::String& recordingsSubDir,
158158
AudioEngine& engine,
159-
std::function<void(const juce::File&)> onProjectChosen)
159+
std::function<void(const juce::File&)> onProjectChosen,
160+
std::function<void()> onWindowClosed)
160161
: DocumentWindow(LanguageManager::getInstance().get("projectListWindow.title"),
161162
juce::Desktop::getInstance().getDefaultLookAndFeel().findColour(juce::ResizableWindow::backgroundColourId),
162-
allButtons)
163+
allButtons),
164+
onWindowClosedCallback(onWindowClosed)
163165
{
164166
setUsingNativeTitleBar(true);
165167
setResizable(true, true);
@@ -173,10 +175,12 @@ ProjectListWindow::ProjectListWindow(const juce::String& recordingsSubDir,
173175
ProjectListWindow::~ProjectListWindow()
174176
{
175177
}
178+
179+
// <<< MODIFIED: Calls the callback, no longer deletes itself >>>
176180
void ProjectListWindow::closeButtonPressed()
177181
{
178-
// Lệnh này sẽ tự động xóa cửa sổ khỏi bộ nhớ một cách an toàn.
179-
delete this;
182+
if (onWindowClosedCallback)
183+
onWindowClosedCallback();
180184
}
181185

182186
void ProjectListWindow::refreshList()

0 commit comments

Comments
 (0)