Skip to content

Apply inputboost ini setting for headless clients - #3841

Open
mcfnord wants to merge 1 commit into
jamulussoftware:mainfrom
mcfnord:fix-inputboost-headless
Open

Apply inputboost ini setting for headless clients#3841
mcfnord wants to merge 1 commit into
jamulussoftware:mainfrom
mcfnord:fix-inputboost-headless

Conversation

@mcfnord

@mcfnord mcfnord commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

MY LLM WROTE:

Follow-up to #3834. While reproducing that bug I found a related, separate defect: a headless client silently ignores the inputboost ini setting. pljones agreed on that thread that it needs its own issue/PR ("Ugh, more 'business logic' in the GUI... Separate issue for this...").

The bug

CClientSettings::ReadSettingsFromXML parses client/inputboost into iInputBoost (settings.cpp:419-422), but the only place that value is ever applied to the client is CClientDlg's constructor:

// clientdlg.cpp:268
pClient->SetInputBoost ( pSettings->iInputBoost );

That line only runs when the GUI dialog is built. A headless client (-n/--nogui, or any JSON-RPC-only session) never constructs CClientDlg, so CClient::SetInputBoost is never called and the boost silently stays at its default (1x, no boost), regardless of what the ini file says.

Verified

I checked whether this is a one-off or a pattern: settings.cpp makes 17 other pClient->Set*() calls from within ReadSettingsFromXML itself (SetAudioInFader, SetReverbLevel, SetSndCrdDev, SetAudioQuality, etc.) — those all work in both GUI and headless mode. SetInputBoost is the only parsed setting with a Set*() method that is not called from ReadSettingsFromXML. Grep for confirmation:

$ grep -oP 'pClient->Set\w+' src/settings.cpp | sort -u | wc -l
17
$ grep -n SetInputBoost src/settings.cpp
421:        iInputBoost = iValue;

(that's on upstream/main before this fix — no SetInputBoost call anywhere in the file outside the value parse. After this fix, line 422 adds it.)

See Testing below for the end-to-end before/after measurement.

Fix

One line, mirroring the existing pattern used by the 17 correctly-wired settings in the same function — apply the value where it's parsed, not only from the dialog:

// settings.cpp
if ( GetNumericIniSet ( IniXMLDocument, "client", "inputboost", 1, 10, iValue ) )
{
    iInputBoost = iValue;
    pClient->SetInputBoost ( iValue );
}

clientdlg.cpp:268 is left as-is — it becomes a redundant re-application of the same value when the GUI is present (harmless, and keeps this diff to the minimum needed for the headless case).

Testing

  • g++ -fsyntax-only clean.
  • clang-format -i — no changes.
  • Full headless build (qmake CONFIG+=headless && make, -DHEADLESS -DWITH_JACK): compiles and links clean under -Wall -Wextra.
  • Confirmed end-to-end with the Fix Input Boost wrapping around instead of clipping #3834 audio rig (JACK dummy → sine → real headless client -n → opus/UDP → real server -R → server-side WAV), same method as that PR. With inputboost=10 in the ini and a −14 dBFS input: unfixed upstream/main (recorded during the Fix Input Boost wrapping around instead of clipping #3834 investigation) gives a peak of 6542 LSB, matching the unboosted level — the ini setting has no effect. The same rig run against this fix gives 32120 LSB, 0.964 correlation to the wrapped-boost model — the boost is now applied. Settings.cpp/clientdlg.cpp are unchanged between the two commits, so the two runs are directly comparable. This branch is off current upstream/main, which doesn't yet include Fix Input Boost wrapping around instead of clipping #3834's clipping fix, so a 10x boost still wraps rather than clips here — that wraparound appearing is exactly the evidence that SetInputBoost is now being called; once Fix Input Boost wrapping around instead of clipping #3834 lands, headless clients will get the clipped behavior for free.

CHANGELOG: Bugfix: headless client now applies the inputboost ini setting (previously silently ignored outside the GUI).

CClientSettings::ReadSettingsFromXML parsed client/inputboost into
iInputBoost but never called CClient::SetInputBoost() outside the
GUI dialog constructor (clientdlg.cpp:268), so headless clients
silently ignored the setting.

Follow-up to jamulussoftware#3834; flagged by pljones on that thread.

Co-Authored-By: Claude <noreply@anthropic.com>
@dingodoppelt dingodoppelt added the AI AI generated or potentially AI generated label Jul 28, 2026
@pljones

pljones commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Is there a method to change this value - i.e. JSONRPC - without the GUI? If not, I think adding that first would be better.

@mcfnord

mcfnord commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

MY LLM WROTE:

@pljones Good point, and I agree — right now this PR only fixes the ini-parse path, so a headless client can set inputboost at startup but has no way to change it at runtime, same gap as the GUI-only SetInputBoost call this PR is patching around.

I can add a jamulusclient/setInputBoost method for it, mirroring the existing setters in clientrpc.cpp (setFaderLevel, setMuted, setSkillLevel, etc.), as a follow-up. Would you rather I fold that into this PR, or keep this PR scoped to the ini-parse fix and open a separate PR for the JSON-RPC setter? Either way works on my end — let me know which you'd prefer.

@pljones

pljones commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

MY LLM WROTE:

@pljones Good point, and I agree — right now this PR only fixes the ini-parse path, so a headless client can set inputboost at startup but has no way to change it at runtime, same gap as the GUI-only SetInputBoost call this PR is patching around.

Oh -- does the Advanced Settings value only apply on start up? I wonder why. If that's the case, it sounds like there's a bigger issue here.

I can add a jamulusclient/setInputBoost method for it, mirroring the existing setters in clientrpc.cpp (setFaderLevel, setMuted, setSkillLevel, etc.), as a follow-up. Would you rather I fold that into this PR, or keep this PR scoped to the ini-parse fix and open a separate PR for the JSON-RPC setter? Either way works on my end — let me know which you'd prefer.

If, indeed, there's a bigger issue, it might be better to close this PR and raise a new one covering the complete fix.

Otherwise, yes - add the JSONRPC to match the Client UI first, then this one. I'd rather not introduce a hole.

@mcfnord

mcfnord commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

MY LLM WROTE:

@pljones No bigger issue — my earlier wording was imprecise, sorry. The Advanced Settings value is not startup-only: CClientSettingsDlg::OnInputBoostChanged (clientsettingsdlg.cpp:1385-1389) is connected to the combo box and calls pClient->SetInputBoost() on every change. The clientdlg.cpp:268 call is a separate one-time apply-on-launch for the persisted value — which is exactly the counterpart this PR adds for headless's ini parse. So the GUI has both paths; headless had neither.

Taking your other branch, then: the JSON-RPC setter is up first as #3843, tested live against a headless client. This PR is the second half and can wait on it.

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

Labels

AI AI generated or potentially AI generated

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants