Commit Graph
19 Commits
Author SHA1 Message Date
OmikronApexandGitHub dee918e705 Merge pull request #113 from got-feedBack/fix/asio-device-lifecycle-message-thread
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
fix(audio): run device lifecycle ops on the JUCE message thread (Windows ASIO UAF)
2026-07-17 00:00:23 +02:00
OmikronApexandGitHub 10bb631ebb Merge pull request #112 from got-feedBack/fix/sync-selected-input-on-device-change
fix(audio): stop stale input selection from clobbering the engine on song start
2026-07-16 22:32:36 +02:00
OmikronApexandGitHub 72a3f871e5 Merge pull request #102 from got-feedBack/fix/nightly-single-portable-zip
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
fix(nightly): ship a single portable zip on Windows
2026-07-12 23:14:36 +02:00
OmikronApexandGitHub ce242a6bcf Merge pull request #100 from got-feedBack/fix/loopback-capture-permission
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
fix(main): permission handler was denying whole-app loopback capture
2026-07-12 01:51:29 +02:00
c71aa7c82f feat(audio): ASIO/exclusive — renderer-bus in streamer mix, loopback plumbing, cache clear (#98)
* feat(audio): renderer-bus in streamer mix + whole-app loopback plumbing

Two tester-confirmed gaps under ASIO/exclusive output:

1. Streamer mix carried guitar only when the song rode the renderer bus:
   composeAndPushStreamMix mixed guitar + native backing, never the bus.
   The bus ring is single-consumer, so the consumer step is reworked from
   mixRendererBusInto (drain+add) to pullRendererBus (drain once into a
   fixed scratch); both output callbacks then share the pulled block
   between the device output and the stream submix (rides includeBacking
   — it IS song audio).

2. Previews/UI sounds bypass the per-surface feeder taps entirely and
   leak to the default WASAPI device (audible under ASIO, which doesn't
   silence that endpoint). New plumbing lets the static bundle capture
   ALL app audio: setDisplayMediaRequestHandler answers with this
   window's own frame as audio source (frame-scoped — no other apps'
   audio), plus audio:setPageMuted IPC + preload setPageMuted() as the
   local-silence fallback when suppressLocalAudioPlayback is unsupported.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(diag): engine health metrics on every [asio-diag] line

Tester symptom: all audio dead after stopping a song with tones active.
The snapshot showed routing state but not whether the engine was still
producing. Append volatile fields (outside change-detection): in/out/
backing levels, bus fill, input overflows, output underflows, split-ring
fill — outputLevel≈0 with running=true is the silent-engine signature.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(main): clear Chromium HTTP cache before first load

Testers hop between portable builds sharing one userData dir; an older
build's server sent no Cache-Control, so its cached /static/app.js
outlived it and silently replaced the new build's renderer code (the
fix14 'watcher never installed' log). One cheap clearCache() per launch
makes stale-bundle states impossible even against old-server caches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:22:30 +02:00
OmikronApexandGitHub f66c27b459 Merge pull request #95 from got-feedBack/diag/asio-routing-debug
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
feat(diag): --debug ASIO routing diagnostics ([asio-diag])
2026-07-11 00:34:36 +02:00
OmikronApexandGitHub 8fa28cf2c2 Merge pull request #94 from got-feedBack/fix/nightly-velopack-entitlements
fix(ci): complete #93 — vpk .entitlements rename + core bundle fixes
2026-07-10 21:03:08 +02:00
OmikronApexandGitHub eca559de76 Merge pull request #93 from got-feedBack/fix/nightly-velopack-entitlements
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
fix(ci): preserve mac entitlements through Velopack re-sign
2026-07-10 14:36:20 +02:00
OmikronApexandGitHub bcbc7963d3 Merge pull request #92 from got-feedBack/fix/mac-tcc-diagnostic-logging
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
fix(mac): add diagnostic logging to microphone TCC permission flow
2026-07-10 00:11:14 +02:00
31248617a5 feat(audio): renderer-audio bus — mix renderer WebAudio master into engine output (Phase 2) (#91)
* fix(audio): prefer same-backend duplex routing

* fix(audio): centre mono input; limit duplex to same-endpoint devices

Two issues found while testing the USB-guitar-cable path on Windows:

1. Centre a mono input. SourceChain::processBlock fell into the
   pass-through branch for a 1-channel input, filling only
   min(inputChannels, outputChannels) = 1 output channel and zeroing the
   rest, so a mono USB guitar cable played out of the left speaker only.
   A single-channel input is now broadcast across every output channel.

2. Only attempt the combined (duplex) device when input and output are
   the SAME physical endpoint. Two different endpoints of the same
   backend (USB cable in + separate speakers out) are independent
   hardware clocks; routing them through one duplex device was unstable
   across the app lifecycle (no audio until an explicit Apply, then
   distortion / dropouts / silent-in-song on navigation). Different
   endpoints now use the split path, whose ring bridges the two clocks.
   Same-endpoint duplex (one interface for in and out) keeps the
   low-latency win. Low latency for the two-device case is a follow-up
   that needs the device-lifecycle work (startup restore + reconfigure
   on navigation).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEoFeTPSnz4NpwwCG52hnu

* fix(audio): probe same-endpoint duplex the same way apply routes it

Startup auto-apply (renderer init) fail-closes on probeDeviceOptionsDual's
`compatible` verdict, but the probe still measured a COMBINED duplex device
for any same-backend pair while setAudioDevices now opens split for
different endpoints. That mismatch made the startup probe describe a config
that isn't the one applied — surfacing as "no audio until I press Apply" for
a USB cable + separate speakers. Gate the probe's duplex path on the same
sameEndpointIntent (same type AND same device) the apply path uses, so a
two-device pair is probed via the split path it will actually run on.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEoFeTPSnz4NpwwCG52hnu

* fix(audio): never feed chain processors blocks larger than prepared size

WASAPI shared mode can deliver oversized blocks right after a device
start. The NAM core pre-allocates its conv ring/output buffers to the
Reset() maxBufferSize and only asserts (release no-op) on larger blocks;
one oversized block corrupts the conv ring state and garbles all
subsequent audio until the next Reset() — the 'first start heavily
distorted until tone reset / engine restart' bug.

- NAMProcessor::processBlock: process in slices of at most the prepared
  block size.
- SignalChain::process: slice oversized device blocks into prepared-size
  chunks before any slot (VST/NAM/IR) sees them.

See docs/audio-distortion-first-start-investigation.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(audio): close stale-format race when processors are added mid-reconfigure

addProcessor/replaceProcessor prepare the incoming processor off the
audio lock on N-API worker threads. A concurrent device reconfigure's
SignalChain::prepare() can't see that processor (not slotted yet), so a
slot could go live prepared at a stale sample rate / block size and stay
wrong until the next device restart — heard as pitch-shifted/garbled
monitoring when a chain loads while the device is being (re)opened
(widest window: WASAPI exclusive mode's slower open).

Re-check the chain's current format under the lock at insert/swap time
and re-prepare if it moved; log the transition to stderr so tester logs
show when the race fired. prepare() now publishes the format under the
lock so the check can't tear.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(effects): align executor plan schema with rebranded capability layer

The rebrand left a three-way schema split: rig_builder sent the old
'slopsmith.audio_effects.chain_plan.v1', the renderer capability layer
validated against the new 'feedBack.…' id (rejecting every plan), and
this executor still expected the old one. Result: every song chain load
fell back to legacy clearChain+loadPreset — a full multi-VST rebuild per
currentSong poll cycle, heard as continuous distortion during playback
(tester logs: 4-6 rebuilds/session, slot IDs into the 90s).

Executor now uses the rebranded id and accepts the legacy one as an
alias (matching the capability layer's new alias), so neither side of
the handoff can break on old plugin bundles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(audio): guard input callback against double registration

Tester main-process log showed two consecutive 'startAudio: duplex=0'
lines: a transient audioDeviceStopped() (WASAPI exclusive opens fire one
mid-start) cleared audioRunning while the input callback stayed
attached, so the second startAudio() re-added it. JUCE then dispatched
the input callback twice per block: DSP ran twice and each block was
pushed into the split ring twice — every sample played twice (half
speed, one octave down, garbled). stopAudio()'s single
removeAudioCallback left the duplicate registration alive, wedging the
engine (restart no longer helped) and keeping the exclusive-mode device
open even after app close.

Mirror the existing outputCallbackRegistered guard for the input side.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(audio): diagnostic instrumentation for tester repro builds

Main-process stderr logging on every open lead, RT paths rate-limited
(first-25 per anomaly + ~5s heartbeats per callback clock):

- primary callback re-entrancy (duplicate registration detector)
- oversized blocks on primary/output callbacks, SignalChain slicing,
  NAM chunking (pre-fix corruption trigger visibility)
- ring fill + under/overflow counters (split-mode pacing)
- device lifecycle: aboutToStart/stopped on both managers with sr/bs and
  callback-registration flags; startAudio guard-skip; stopAudio state
- SourceChain.prepare format trace (stale-rate lead)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(audio): drop diagnostic heartbeats, keep anomaly detectors

The 5s ring/format heartbeats served the distortion hunt and are noise
now. Keep the cheap anomaly-only diagnostics (callback re-entrancy,
oversized-block detectors, chain slicing/chunking, stale-format
re-prepare, device lifecycle) — they log only on misbehavior and stay
relevant for the exclusive-mode playback work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: keep investigation notes out of the PR (local working notes)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: pin JUCE WASAPI exclusive device-type name

The shared player bundle (feedBack#824) detects exclusive-style output
by string-matching getCurrentDevice().outputType. The name is hardcoded
in vendored JUCE; a JUCE upgrade renaming it would silently disable the
feedpak-under-exclusive routing. Fail the build instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(audio): renderer-audio bus — mix renderer WebAudio master into engine output (Phase 2)

SPSC packed-LR ring (64K frames) fed over IPC by the renderer, consumed by
whichever output callback is live (duplex or split), mixed like a backing
track before master gain. Producer-side linear resampling with cross-chunk
continuity; drop-oldest on overflow. Prefill gate (~10.7 ms) and fill clamp
(~85 ms → trim to prime target) added from fix12 tester spike data, which
also confirmed clock stability (drift → 0, zero overflow over 8 min).
Off by default — zero behavior change until the renderer enables it.

Exposed as setRendererBus / pushRendererAudio (fire-and-forget IPC,
~100 msgs/s) / getRendererBusMetrics. Spike script included for tester
go/no-go runs. Consumed by the feeder in feedBack#824's Phase 2 follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(audio): gate lifecycle [diag] logs behind SLOPSMITH_SANDBOX_DEBUG

Review follow-up (#86): the six lifecycle diagnostics (stopAudio,
audioDeviceAboutToStart/Stopped, audioOutputAboutToStart/Stopped,
SourceChain::prepare) printed unconditionally while the PR body claimed
they were verbose-gated. Gate them behind the existing
slopsmith_vst_trace::isEnabled() runtime flag (SLOPSMITH_SANDBOX_DEBUG —
already flipped by the app's debug-logging switch, so tester debug runs
still capture them). The RT-path anomaly detectors (primary re-entry,
oversized-block) keep their firstN/anomaly bounds unchanged, as reviewed.

VSTTrace.h now defines NOMINMAX/WIN32_LEAN_AND_MEAN before windows.h so
including it from engine TUs doesn't clobber std::min.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: ChrisBeWithYou <chris@rifflarr.local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 23:03:31 +02:00
2d0dd12abe fix(audio): input-callback double registration, stale-format race, effects schema alignment (#86)
* fix(audio): prefer same-backend duplex routing

* fix(audio): centre mono input; limit duplex to same-endpoint devices

Two issues found while testing the USB-guitar-cable path on Windows:

1. Centre a mono input. SourceChain::processBlock fell into the
   pass-through branch for a 1-channel input, filling only
   min(inputChannels, outputChannels) = 1 output channel and zeroing the
   rest, so a mono USB guitar cable played out of the left speaker only.
   A single-channel input is now broadcast across every output channel.

2. Only attempt the combined (duplex) device when input and output are
   the SAME physical endpoint. Two different endpoints of the same
   backend (USB cable in + separate speakers out) are independent
   hardware clocks; routing them through one duplex device was unstable
   across the app lifecycle (no audio until an explicit Apply, then
   distortion / dropouts / silent-in-song on navigation). Different
   endpoints now use the split path, whose ring bridges the two clocks.
   Same-endpoint duplex (one interface for in and out) keeps the
   low-latency win. Low latency for the two-device case is a follow-up
   that needs the device-lifecycle work (startup restore + reconfigure
   on navigation).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEoFeTPSnz4NpwwCG52hnu

* fix(audio): probe same-endpoint duplex the same way apply routes it

Startup auto-apply (renderer init) fail-closes on probeDeviceOptionsDual's
`compatible` verdict, but the probe still measured a COMBINED duplex device
for any same-backend pair while setAudioDevices now opens split for
different endpoints. That mismatch made the startup probe describe a config
that isn't the one applied — surfacing as "no audio until I press Apply" for
a USB cable + separate speakers. Gate the probe's duplex path on the same
sameEndpointIntent (same type AND same device) the apply path uses, so a
two-device pair is probed via the split path it will actually run on.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEoFeTPSnz4NpwwCG52hnu

* fix(audio): never feed chain processors blocks larger than prepared size

WASAPI shared mode can deliver oversized blocks right after a device
start. The NAM core pre-allocates its conv ring/output buffers to the
Reset() maxBufferSize and only asserts (release no-op) on larger blocks;
one oversized block corrupts the conv ring state and garbles all
subsequent audio until the next Reset() — the 'first start heavily
distorted until tone reset / engine restart' bug.

- NAMProcessor::processBlock: process in slices of at most the prepared
  block size.
- SignalChain::process: slice oversized device blocks into prepared-size
  chunks before any slot (VST/NAM/IR) sees them.

See docs/audio-distortion-first-start-investigation.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(audio): close stale-format race when processors are added mid-reconfigure

addProcessor/replaceProcessor prepare the incoming processor off the
audio lock on N-API worker threads. A concurrent device reconfigure's
SignalChain::prepare() can't see that processor (not slotted yet), so a
slot could go live prepared at a stale sample rate / block size and stay
wrong until the next device restart — heard as pitch-shifted/garbled
monitoring when a chain loads while the device is being (re)opened
(widest window: WASAPI exclusive mode's slower open).

Re-check the chain's current format under the lock at insert/swap time
and re-prepare if it moved; log the transition to stderr so tester logs
show when the race fired. prepare() now publishes the format under the
lock so the check can't tear.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(effects): align executor plan schema with rebranded capability layer

The rebrand left a three-way schema split: rig_builder sent the old
'slopsmith.audio_effects.chain_plan.v1', the renderer capability layer
validated against the new 'feedBack.…' id (rejecting every plan), and
this executor still expected the old one. Result: every song chain load
fell back to legacy clearChain+loadPreset — a full multi-VST rebuild per
currentSong poll cycle, heard as continuous distortion during playback
(tester logs: 4-6 rebuilds/session, slot IDs into the 90s).

Executor now uses the rebranded id and accepts the legacy one as an
alias (matching the capability layer's new alias), so neither side of
the handoff can break on old plugin bundles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(audio): guard input callback against double registration

Tester main-process log showed two consecutive 'startAudio: duplex=0'
lines: a transient audioDeviceStopped() (WASAPI exclusive opens fire one
mid-start) cleared audioRunning while the input callback stayed
attached, so the second startAudio() re-added it. JUCE then dispatched
the input callback twice per block: DSP ran twice and each block was
pushed into the split ring twice — every sample played twice (half
speed, one octave down, garbled). stopAudio()'s single
removeAudioCallback left the duplicate registration alive, wedging the
engine (restart no longer helped) and keeping the exclusive-mode device
open even after app close.

Mirror the existing outputCallbackRegistered guard for the input side.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(audio): diagnostic instrumentation for tester repro builds

Main-process stderr logging on every open lead, RT paths rate-limited
(first-25 per anomaly + ~5s heartbeats per callback clock):

- primary callback re-entrancy (duplicate registration detector)
- oversized blocks on primary/output callbacks, SignalChain slicing,
  NAM chunking (pre-fix corruption trigger visibility)
- ring fill + under/overflow counters (split-mode pacing)
- device lifecycle: aboutToStart/stopped on both managers with sr/bs and
  callback-registration flags; startAudio guard-skip; stopAudio state
- SourceChain.prepare format trace (stale-rate lead)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(audio): drop diagnostic heartbeats, keep anomaly detectors

The 5s ring/format heartbeats served the distortion hunt and are noise
now. Keep the cheap anomaly-only diagnostics (callback re-entrancy,
oversized-block detectors, chain slicing/chunking, stale-format
re-prepare, device lifecycle) — they log only on misbehavior and stay
relevant for the exclusive-mode playback work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: keep investigation notes out of the PR (local working notes)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(audio): gate lifecycle [diag] logs behind SLOPSMITH_SANDBOX_DEBUG

Review follow-up (#86): the six lifecycle diagnostics (stopAudio,
audioDeviceAboutToStart/Stopped, audioOutputAboutToStart/Stopped,
SourceChain::prepare) printed unconditionally while the PR body claimed
they were verbose-gated. Gate them behind the existing
slopsmith_vst_trace::isEnabled() runtime flag (SLOPSMITH_SANDBOX_DEBUG —
already flipped by the app's debug-logging switch, so tester debug runs
still capture them). The RT-path anomaly detectors (primary re-entry,
oversized-block) keep their firstN/anomaly bounds unchanged, as reviewed.

VSTTrace.h now defines NOMINMAX/WIN32_LEAN_AND_MEAN before windows.h so
including it from engine TUs doesn't clobber std::min.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: ChrisBeWithYou <chris@rifflarr.local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 22:44:15 +02:00
91c4e0037f test: pin JUCE WASAPI exclusive device-type name (#90)
The shared player bundle (feedBack#824) detects exclusive-style output
by string-matching getCurrentDevice().outputType. The name is hardcoded
in vendored JUCE; a JUCE upgrade renaming it would silently disable the
feedpak-under-exclusive routing. Fail the build instead.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 22:18:04 +02:00
3e3f1f868c fix(audio): never feed chain processors blocks larger than prepared size (#85)
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
* fix(audio): never feed chain processors blocks larger than prepared size

WASAPI shared mode can deliver oversized blocks right after a device
start. The NAM core pre-allocates its conv ring/output buffers to the
Reset() maxBufferSize and only asserts (release no-op) on larger blocks;
one oversized block corrupts the conv ring state and garbles all
subsequent audio until the next Reset() — the 'first start heavily
distorted until tone reset / engine restart' bug.

- NAMProcessor::processBlock: process in slices of at most the prepared
  block size.
- SignalChain::process: slice oversized device blocks into prepared-size
  chunks before any slot (VST/NAM/IR) sees them.

See docs/audio-distortion-first-start-investigation.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(audio): prefer same-backend duplex routing

* fix(audio): centre mono input; limit duplex to same-endpoint devices

Two issues found while testing the USB-guitar-cable path on Windows:

1. Centre a mono input. SourceChain::processBlock fell into the
   pass-through branch for a 1-channel input, filling only
   min(inputChannels, outputChannels) = 1 output channel and zeroing the
   rest, so a mono USB guitar cable played out of the left speaker only.
   A single-channel input is now broadcast across every output channel.

2. Only attempt the combined (duplex) device when input and output are
   the SAME physical endpoint. Two different endpoints of the same
   backend (USB cable in + separate speakers out) are independent
   hardware clocks; routing them through one duplex device was unstable
   across the app lifecycle (no audio until an explicit Apply, then
   distortion / dropouts / silent-in-song on navigation). Different
   endpoints now use the split path, whose ring bridges the two clocks.
   Same-endpoint duplex (one interface for in and out) keeps the
   low-latency win. Low latency for the two-device case is a follow-up
   that needs the device-lifecycle work (startup restore + reconfigure
   on navigation).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEoFeTPSnz4NpwwCG52hnu

* fix(audio): probe same-endpoint duplex the same way apply routes it

Startup auto-apply (renderer init) fail-closes on probeDeviceOptionsDual's
`compatible` verdict, but the probe still measured a COMBINED duplex device
for any same-backend pair while setAudioDevices now opens split for
different endpoints. That mismatch made the startup probe describe a config
that isn't the one applied — surfacing as "no audio until I press Apply" for
a USB cable + separate speakers. Gate the probe's duplex path on the same
sameEndpointIntent (same type AND same device) the apply path uses, so a
two-device pair is probed via the split path it will actually run on.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEoFeTPSnz4NpwwCG52hnu

* fix(audio): close stale-format race when processors are added mid-reconfigure

addProcessor/replaceProcessor prepare the incoming processor off the
audio lock on N-API worker threads. A concurrent device reconfigure's
SignalChain::prepare() can't see that processor (not slotted yet), so a
slot could go live prepared at a stale sample rate / block size and stay
wrong until the next device restart — heard as pitch-shifted/garbled
monitoring when a chain loads while the device is being (re)opened
(widest window: WASAPI exclusive mode's slower open).

Re-check the chain's current format under the lock at insert/swap time
and re-prepare if it moved; log the transition to stderr so tester logs
show when the race fired. prepare() now publishes the format under the
lock so the check can't tear.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: ChrisBeWithYou <chris@rifflarr.local>
2026-07-08 22:44:26 +02:00
OmikronApexandGitHub a53fd38732 Merge pull request #84 from got-feedBack/chore/plugin-manager-rebrand
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
chore(plugin-manager): rebrand UI strings from Slopsmith to fee[dB]ack
2026-07-08 09:55:58 +02:00
OmikronApexandGitHub ac824d5cc5 Merge pull request #81 from got-feedBack/chore/drop-setlist-plugin
Addon CI / addon (arm64, macos-14, mac) (push) Waiting to run
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Waiting to run
Addon CI / addon (x64, windows-latest, win) (push) Waiting to run
Ship CI / CI (push) Waiting to run
chore(build): stop bundling feedback-plugin-setlist
2026-07-07 19:20:30 +02:00
OmikronApexandGitHub 34e1aa099d Change nightly workflow schedule to 23:00
Addon CI / addon (arm64, macos-14, mac) (push) Has been cancelled
Addon CI / addon (x64, ubuntu-22.04, linux) (push) Has been cancelled
Addon CI / addon (x64, windows-latest, win) (push) Has been cancelled
Ship CI / CI (push) Has been cancelled
2026-07-05 22:48:36 +02:00
OmikronApexandGitHub 8083fc2b2c Merge pull request #77 from got-feedBack/ci/fix-slopsmith-rename
ci(build): stop full matrix on pushes to main
2026-07-03 18:07:00 +02:00
OmikronApexandGitHub 8ca63f2a09 Merge pull request #76 from got-feedBack/ci/fix-slopsmith-rename
ci(nightly): fix macOS/Windows packaging broken by fee[dB]ack rename
2026-07-03 17:43:25 +02:00
921ae0b66d ci: adapt workflows to trunk-based development (#62)
* ci: adapt workflows to trunk-based development

Nightly builds main directly (old release/v* discovery pinned nightlies
to shipped branches forever). ship-ci adds push triggers on main and
release/** for post-merge signal. New rc.yml builds the desktop app
matrix from release branches during stabilization (signed, not
notarized, 14-day artifacts).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: fix rc.yml mac-zip rename skew + drop duplicate build-core

rc.yml: glob release/mac*/*.app (was hardcoded Slopsmith.app, which no longer exists after the fee[dB]ack rebrand) and derive the zip name from the bundle; rename the win zip + comments off 'Slopsmith'. nightly.yml: remove build-core — core's own nightly already pushes ghcr feedback:nightly on the same cron (duplicate/race, per PR author's open question).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: byrongamatos <xasiklas@gmail.com>
2026-07-03 11:29:33 +02:00