Skip to content

Commit 0535b67

Browse files
authored
Workaround normalisation enabled during render (#301)
* Simulate clicks on checkboxes to fire listeners * Allow checkbox to disable normalisation button itself * Logic around button disabling and warning * Update CHANGELOG.md
1 parent 356cefa commit 0535b67

File tree

3 files changed

+40
-57
lines changed

3 files changed

+40
-57
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ UNRELEASED
88
* Use ADM Coordinate Conversion lib over internal implementation [#293](https://github.com/ebu/ear-production-suite/issues/293) [#295](https://github.com/ebu/ear-production-suite/pull/295)
99
* Remove support for 3rd-party plugin suites [#289](https://github.com/ebu/ear-production-suite/pull/289)
1010
* Update render dialog code to support latest version of REAPER (v7.34) [#296](https://github.com/ebu/ear-production-suite/issues/296) [#297](https://github.com/ebu/ear-production-suite/pull/297)
11+
* Give warning for older REAPER versions if user attempts to render with normalisation [#301](https://github.com/ebu/ear-production-suite/pull/301)
1112

1213
Version 1.1.0b
1314

reaper-adm-extension/src/reaper_adm/exportaction_dialogcontrol.cpp

Lines changed: 38 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,13 @@ bool RenderDialogState::getCheckboxState(HWND hwnd)
174174

175175
void RenderDialogState::setCheckboxState(HWND hwnd, bool state)
176176
{
177-
SendMessage(hwnd, BM_SETCHECK, state? BST_CHECKED : BST_UNCHECKED, 0);
177+
auto currentState = getCheckboxState(hwnd);
178+
if (state == currentState) return;
179+
// Have to simulate a click in case it has a listener attached to it
180+
auto parentHwnd = GetParent(hwnd);
181+
auto controlId = GetWindowLong(hwnd, GWL_ID);
182+
SendMessage(hwnd, BM_SETCHECK, state ? BST_CHECKED : BST_UNCHECKED, 0);
183+
SendMessage(parentHwnd, WM_COMMAND, MAKELONG(controlId, BN_CLICKED), (LPARAM)hwnd);
178184
}
179185

180186
void RenderDialogState::startPreparingRenderControls(HWND hwndDlg)
@@ -184,9 +190,6 @@ void RenderDialogState::startPreparingRenderControls(HWND hwndDlg)
184190
localise(EXPECTED_FIRST_CHANNEL_COUNT_COMBO_OPTION, reaperApi);
185191
localise(EXPECTED_PRESETS_BUTTON_TEXT, reaperApi);
186192
localise(EXPECTED_PRESERVE_SAMPLE_RATE_CHECKBOX_TEXT, reaperApi);
187-
localise(EXPECTED_NORMALIZE_BUTTON_TEXT1, reaperApi);
188-
localise(EXPECTED_NORMALIZE_BUTTON_TEXT2, reaperApi);
189-
localise(EXPECTED_NORMALIZE_BUTTON_TEXT3, reaperApi);
190193
localise(EXPECTED_SECOND_PASS_CHECKBOX_TEXT, reaperApi);
191194
localise(EXPECTED_MONO2MONO_CHECKBOX_TEXT, reaperApi);
192195
localise(EXPECTED_MULTI2MULTI_CHECKBOX_TEXT, reaperApi);
@@ -197,7 +200,6 @@ void RenderDialogState::startPreparingRenderControls(HWND hwndDlg)
197200
localise(EXPECTED_FIRST_RESAMPLE_MODE_COMBO_OPTION, reaperApi);
198201

199202
// Our dialog displayed - reset all vars (might not be the first time around)
200-
lastFoundButtonHwnd.reset();
201203
boundsControlHwnd.reset();
202204
sourceControlHwnd.reset();
203205
presetsControlHwnd.reset();
@@ -213,6 +215,7 @@ void RenderDialogState::startPreparingRenderControls(HWND hwndDlg)
213215
resampleModeControlHwnd.reset();
214216
sampleRateControlSetError = false;
215217
channelsControlSetError = false;
218+
normalisationOptionsEnabled = false;
216219
sampleRateLastOption.clear();
217220
channelsLastOption.clear();
218221

@@ -285,6 +288,17 @@ BOOL CALLBACK RenderDialogState::prepareRenderControl_pass1(HWND hwnd, LPARAM lP
285288
}
286289
}
287290

291+
if (controlType == BUTTON) {
292+
// Normalise checkbox has no text, and order of control enumeration may not be reliable. Lets check ID.
293+
// Do this in first pass as we don't want to disable the normalisation button if the checkbox isn't present.
294+
if (GetWindowLong(hwnd, GWL_ID) == EXPECTED_NORMALIZE_CHECKBOX_ID) {
295+
assert(getWindowText(hwnd) == "");
296+
normalizeCheckboxControlHwnd = hwnd;
297+
normalizeCheckboxLastState = getCheckboxState(hwnd);
298+
setCheckboxState(hwnd, false);
299+
EnableWindow(hwnd, false);
300+
}
301+
}
288302
}
289303

290304
return true; // MUST return true to continue iterating through controls
@@ -307,41 +321,6 @@ BOOL CALLBACK RenderDialogState::prepareRenderControl_pass2(HWND hwnd, LPARAM lP
307321
presetsControlHwnd = hwnd;
308322
EnableWindow(hwnd, false);
309323
}
310-
311-
if (winStr == EXPECTED_NORMALIZE_BUTTON_TEXT1 ||
312-
winStr == EXPECTED_NORMALIZE_BUTTON_TEXT2 ||
313-
winStr == EXPECTED_NORMALIZE_BUTTON_TEXT3){
314-
// This is the normalization config which will not work for this as we don't use the sink feed anyway - disable it
315-
if (winStr == EXPECTED_NORMALIZE_BUTTON_TEXT3) {
316-
// This control has a seperate, unlabeled checkbox before it - see if we just passed it
317-
if (lastFoundButtonHwnd &&
318-
getControlType(*lastFoundButtonHwnd) == BUTTON &&
319-
getWindowText(*lastFoundButtonHwnd) == "") {
320-
normalizeCheckboxControlHwnd = lastFoundButtonHwnd;
321-
normalizeCheckboxLastState = getCheckboxState(*lastFoundButtonHwnd);
322-
setCheckboxState(*lastFoundButtonHwnd, false);
323-
EnableWindow(*lastFoundButtonHwnd, false);
324-
}
325-
}
326-
normalizeControlHwnd = hwnd;
327-
EnableWindow(hwnd, false);
328-
}
329-
// Normalise button text changes depending on what options are enabled.
330-
// Lets check ID too
331-
if (id == EXPECTED_NORMALIZE_BUTTON_ID && !normalizeControlHwnd.has_value()) {
332-
normalizeControlHwnd = hwnd;
333-
EnableWindow(hwnd, false);
334-
}
335-
// Normalise checkbox has no text, and order of control enumeration may not be reliable.
336-
// Lets check ID too
337-
if (id == EXPECTED_NORMALIZE_CHECKBOX_ID && !normalizeCheckboxControlHwnd.has_value()) {
338-
assert(winStr == "");
339-
normalizeCheckboxControlHwnd = hwnd;
340-
normalizeCheckboxLastState = getCheckboxState(hwnd);
341-
setCheckboxState(hwnd, false);
342-
EnableWindow(hwnd, false);
343-
}
344-
345324
if (winStr == EXPECTED_SECOND_PASS_CHECKBOX_TEXT){
346325
// 2nd pass render causes a mismatch between expected number of received block and actual number of received blocks (double)
347326
// Could probably be recified, but disable as quick fix for now
@@ -368,6 +347,18 @@ BOOL CALLBACK RenderDialogState::prepareRenderControl_pass2(HWND hwnd, LPARAM lP
368347
setCheckboxState(hwnd, false);
369348
EnableWindow(hwnd, false);
370349
}
350+
// Normalise button text changes depending on what options are enabled. Lets check ID instead.
351+
if (id == EXPECTED_NORMALIZE_BUTTON_ID) {
352+
// We only disable the button if there isn't a checkbox (otherwise the checkbox handles state and disables normalisation),
353+
// and if no normalisation is set, otherwise we have to leave so the user can switch normalisation off.
354+
if (!normalizeCheckboxControlHwnd.has_value()) {
355+
normalisationOptionsEnabled = winStr.ends_with(" ON");
356+
if (!normalisationOptionsEnabled) {
357+
normalizeControlHwnd = hwnd;
358+
EnableWindow(hwnd, false);
359+
}
360+
}
361+
}
371362
}
372363

373364
if (controlType == TEXT || controlType == EDITABLECOMBO) {
@@ -400,9 +391,6 @@ BOOL CALLBACK RenderDialogState::prepareRenderControl_pass2(HWND hwnd, LPARAM lP
400391

401392
}
402393

403-
if (controlType == BUTTON) {
404-
lastFoundButtonHwnd = hwnd;
405-
}
406394
return true; // MUST return true to continue iterating through controls
407395
}
408396

@@ -517,6 +505,9 @@ WDL_DLGRET RenderDialogState::wavecfgDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPa
517505
if(!allControlsSuccessful) {
518506
infoPaneText = "WARNING: Unable to takeover all render controls. REAPER version may be unsupported and render may fail.\r\n\r\n" + infoPaneText;
519507
}
508+
if (normalisationOptionsEnabled) {
509+
infoPaneText = "WARNING: Built-in normalisation is not compatible with object-based audio. Render will fail. Please disable any normalisation/limiting/fade.\r\n\r\n" + infoPaneText;
510+
}
520511

521512
SetWindowText(GetDlgItem(hwndDlg, IDC_INFOPANE), LPCSTR(infoPaneText.c_str()));
522513
EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_REFRESH), true);
@@ -561,6 +552,7 @@ WDL_DLGRET RenderDialogState::wavecfgDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPa
561552
if(boundsControlHwnd) EnableWindow(*boundsControlHwnd, true);
562553
if(presetsControlHwnd) EnableWindow(*presetsControlHwnd, true);
563554
if(sourceControlHwnd) EnableWindow(*sourceControlHwnd, true);
555+
if (normalizeControlHwnd) EnableWindow(*normalizeControlHwnd, true);
564556

565557
if(secondPassControlHwnd) {
566558
EnableWindow(*secondPassControlHwnd, true);
@@ -578,15 +570,9 @@ WDL_DLGRET RenderDialogState::wavecfgDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPa
578570
EnableWindow(*preserveSampleRateControlHwnd, true);
579571
setCheckboxState(*preserveSampleRateControlHwnd, preserveSampleRateLastState);
580572
}
581-
if (normalizeControlHwnd) {
582-
if (normalizeCheckboxControlHwnd) {
583-
EnableWindow(*normalizeCheckboxControlHwnd, true);
584-
setCheckboxState(*normalizeCheckboxControlHwnd, normalizeCheckboxLastState);
585-
EnableWindow(*normalizeControlHwnd, normalizeCheckboxLastState); // Only reenable if last state was checked
586-
}
587-
else {
588-
EnableWindow(*normalizeControlHwnd, true);
589-
}
573+
if (normalizeCheckboxControlHwnd) {
574+
EnableWindow(*normalizeCheckboxControlHwnd, true);
575+
setCheckboxState(*normalizeCheckboxControlHwnd, normalizeCheckboxLastState);
590576
}
591577

592578
// NOTE: Sample Rate and Channels controls are;

reaper-adm-extension/src/reaper_adm/exportaction_dialogcontrol.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ class RenderDialogState {
4343
std::shared_ptr<ReaperAPI> reaperApi;
4444
REAPER_PLUGIN_HINSTANCE reaperInst;
4545

46-
std::optional<HWND> lastFoundButtonHwnd{};
47-
4846
std::optional<HWND> boundsControlHwnd{};
4947
std::optional<HWND> sourceControlHwnd{};
5048
std::optional<HWND> presetsControlHwnd{};
@@ -60,6 +58,7 @@ class RenderDialogState {
6058
std::optional<HWND> preserveSampleRateControlHwnd{};
6159
bool sampleRateControlSetError{false};
6260
bool channelsControlSetError{false};
61+
bool normalisationOptionsEnabled{false};
6362

6463
std::string sampleRateLastOption{};
6564
std::string channelsLastOption{};
@@ -84,9 +83,6 @@ class RenderDialogState {
8483
std::string EXPECTED_FIRST_CHANNEL_COUNT_COMBO_OPTION{ "Mono" };
8584
std::string EXPECTED_PRESETS_BUTTON_TEXT{ "Presets" };
8685
std::string EXPECTED_PRESERVE_SAMPLE_RATE_CHECKBOX_TEXT{ "Preserve source media sample rate if possible" };
87-
std::string EXPECTED_NORMALIZE_BUTTON_TEXT1{ "Normalize/Limit..." };
88-
std::string EXPECTED_NORMALIZE_BUTTON_TEXT2{ "Normalize/Limit/Fade" }; // Changed to include fade at ~v6.64
89-
std::string EXPECTED_NORMALIZE_BUTTON_TEXT3{ "Normalize/fade" }; // Changed to remove limit at ~v7.34 - includes an unlabelled checkbox alongside
9086
const int EXPECTED_NORMALIZE_BUTTON_ID{ 1067 };
9187
const int EXPECTED_NORMALIZE_CHECKBOX_ID{ 1069 };
9288
std::string EXPECTED_SECOND_PASS_CHECKBOX_TEXT{ "2nd pass render" };

0 commit comments

Comments
 (0)