Skip to content

Mixer: a console of strips with meters, and the execution reporting back without stopping the audio - #2302

Open
jcelerier wants to merge 39 commits into
masterfrom
feature/mixer
Open

jcelerier wants to merge 39 commits into
masterfrom
feature/mixer

Conversation

@jcelerier

Copy link
Copy Markdown
Member

A rework of the audio mixer panel and of how the execution reports back to the interface. 35 commits, each with its test where one applies. Everything visual was checked in a running score rather than by unit test alone.

Needs ossia/libossia#950 and celtera/avendish#210. The submodule pointers here already reference them. An adversarial review of the whole branch was run before opening this. Its findings are fixed in the last commits, except one that is kept by design (see below).

Mixer panel

  • One console. The sections are Buses, Inputs, Outputs, Mapped and Virtual. Each folds away behind a vertical tab on its side. The master /out/main is pinned on the right. Every row lines up across strips (title, channel count, meter and fader, readout, controls).
  • Meters. score::LevelMeter is a multichannel meter with peak hold, an RMS line and clip marks. It keeps the widest channel count seen, so a width change does not make it jump.
  • Bus strips:
    • mute, solo and propagate;
    • balance and output routing;
    • an upmix menu (repeat the channels, or add silent ones, up to N);
    • per-channel gains for a wide bus;
    • a channel count and CPU readout;
    • selection linked with the score.
  • Port strips: hardware inputs and outputs, mapped ports (metered on their hardware channels) and virtual ports. The "+" in the Mapped and Virtual tabs adds a port, and a strip's menu edits or removes it. Input meters show the level after the gain it is read with.
  • Widths. A strip's width is set from its menu, and every strip's from a tab's menu. The toolbar volume follows the master.

Model and commands

  • Mute and solo on intervals are undoable and saved. Solo keeps the soloed bus's ancestors and descendants heard. Both act through the existing interval mute, which disables everything in the interval.
  • Upmix mode and channel count on audio outlets, with commands and serialization.
  • Port gains. The gain of a port of the audio device (Audio::SetPortGain; score-plugin-audio now has commands) is one undo step when a fader or the toolbar volume is released. It is saved as the node's audio-gain attribute and restored on load and on reconnection.
  • Gain, pan and upmix reach the running outlet of every process, not only of intervals (SetupContext::register_mixing_impl). The model offered them on every audio outlet.
  • Older binary data. Binary data written before mute, solo and upmix existed still reads: DataStreamWriter::atDelimiterOrEnd makes added fields optional.

Execution → interface

  • Execution::Telemetry (score-plugin-engine), with Process::TelemetryInterface in score-lib-process, reads libossia's telemetry arena at the document's coarse rate, under the execution-update setting. Meters can be asked for on outlets, inlets, hardware inputs and outputs, and virtual ports. The benchmark goes through bench taps, which lifts the old per-50-ticks hash-map copy.
  • Moved onto it or onto triple buffers:
    • interval playheads (only start and stop remain commands, since executing() has model effects);
    • avendish control values;
    • Faust control and display values;
    • YSFX sliders;
    • the pattern sequencer's step;
    • LV2 control outputs.
  • LV2. The LV2 interface read voice 0's buffers on the UI thread, every tick, while the audio thread wrote them. Its MIDI for the plug-in window is now copied at the end of the tick, into a bounded queue, only while the window is open.
  • Gating. avendish and JS messages to the interface follow the execution-update setting.

Real-time safety and lifetimes

  • No stopping the audio. Nothing stops the audio to make a change safe. Changes to what the callback reads run between two ticks (audio_engine::run_between_ticks), or are prepared and swapped in. The audio device edits, adds and removes ports this way while playing, in place, because running processes hold pointers to them.
  • Removing a node while playing used to crash as soon as a process had written to it.
    • Devices announce a subtree before removing it (DeviceInterface::nodeAboutToBeRemoved).
    • The meters under it let go first.
    • When a process port may point there, the ports drop those addresses between two ticks, once for the whole removal.
    • The audio device is followed across its reconnections.
  • Showing the audio device in the device explorer reconnected it, which stopped the audio during playback. That happened when adding a port or recording a gain from the mixer. A reconnection with the same engine and channels now leaves its tree alone.

Also

  • Master gain. It is applied once the tick is summed, and a run starts at it.
  • AudioDevice::portsChanged is emitted when a port is added, edited or removed.
  • Dummy backend. It has the channels the settings ask for.
  • Sliders. A value typed in a slider's popup ends the gesture.
  • VU Meter. It reads its inlet through the telemetry, and its Levels output stops allocating once warm.

Worth a second opinion

  • Solo as a mute. Solo silences the other buses through the interval mute, as decided, so their MIDI, OSC, video and automation stop too.
  • AudioDevice::reconnect now returns early when the tree was built for the same engine (held as a weak_ptr) and channel counts. updateSettings disconnects first, so a settings change still rebuilds, and an engine restart is another engine.
  • Removal filter. Deciding whether a removal needs the between-ticks pass uses the model ports' addresses: same device, and either a path prefix or a pattern. This is conservative on patterns.
  • Plug-in feedback gating (avendish, JS) is decided when the execution is set up, so toggling the setting mid-run applies from the next play.
  • Pattern destinations. Addresses written as patterns are still resolved against a tree the interface may be deleting. This predates the branch.

Tests

New or extended:

  • test_unit_telemetry_exec: meters, a virtual port removed while playing, 200 ports removed while playing (once, under a second, with and without a device rebuild), and gain, pan and upmix propagation;
  • test_unit_audio_port_edit: live edits, and a gain that is undone, redone and survives a JSON reload;
  • test_integration_interval_mute_solo;
  • test_unit_avnd_control_outputs_ui;
  • test_unit_faust_dsp: generators with and without a cable;
  • test_unit_lv2_loading: control outputs through the triple buffer;
  • test_unit_datastream_compat.

Known red before any of this, unchanged: js_remove_cable (the test profile has no default package).

🤖 Generated with Claude Code

https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX

@jcelerier

Copy link
Copy Markdown
Member Author

The AppImage aarch64 failure on 63e2c52 comes from score-addon-librediffusion: it vendored ossia::triple_buffer in namespace ossia, and the avendish binding now includes libossia's own header. Fixed there in ossia/score-addon-librediffusion#24 (backward compatible, can be merged first); CI clones that add-on's default branch, so this job needs #24 merged.

@coveralls

coveralls commented Sep 25, 2026 •

Copy link
Copy Markdown

Coverage Status

Coverage is 48.723% — feature/mixer into master. No base build found for master.

edumeneses added a commit to edumeneses/score that referenced this pull request Oct 8, 2026
EXTRA_PRS names PRs of other authors on ossia/score to merge into the build
alongside mine, starting with ossia#2302 (jcelerier's mixer console). Each one is
merged only while its state is OPEN, so a PR that gets merged or closed drops
out of the build without touching the workflow; the run leaves a notice so the
number can be cleaned out of the list later. The release body names the author
of such PRs (without an @, so the release does not mention them).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lc7tYGHRn6TmaxMEfBTswW
@edumeneses

Copy link
Copy Markdown
Contributor

This is Edu's Claude assistant, posting on Edu's behalf.

Rebased onto master (bf4c7f5ee0), together with its submodule PRs, so that it merges again. Same 38 commits, same messages and authorship. Every submodule bump points at the rebased counterpart of the libossia commit it pointed at before, so each step still builds against its own libossia.

Submodules

Where master and the PR overlapped

  • Toolbar volume (audio: the toolbar volume shows the master gain): master's showVolume() (6bcc0ff) did what syncVolume() does. It is gone, and its two call sites (after a rebind, on engine start) call syncVolume(). That keeps m_shownVolume, the "before" of the undoable gain, in step.
  • Saved master volume (AudioDevice): master restores the saved value of a node, and carries the live values over a reconnect. The PR restores its audio-gain attribute and swaps the ports between ticks. Both are kept: setupNode(), then the saved value, then applyGain(); on reconnect the carried-over live values come last.
  • Device lifetimes (execution: let go of removed nodes…, against master's 69469be and 6890fcc): master's onDeviceChanged() is the one handler. That covers bool register/unregister, triggers and conditions rebuilt, and the wait on the execution queue. It now also does the PR's m_telemetry->forgetUnder(old), and the PR's on_deviceChanged() is gone. The connections live in followDevice(), which also connects nodeAboutToBeRemoved (direct). The audio device is followed from the constructor and skipped in on_deviceAdded(), as in the PR. DeviceInterface has both deviceClearing and nodeAboutToBeRemoved, emitted in that order by disconnect().
  • RegisteredPorts: master's several connections per port plus the PR's mixing map.
  • DocumentPlugin.cpp: bench_state.hpp replaces bench_map.hpp; master's algorithms.hpp stays.
  • LV2 (lv2: stop reading the running plug-in's buffers…): master's close-window drain goes through plugin_events->queue, and master's new LV2 test hooks get the on_finished(node) overload.
  • ExecutionEditCommandsTest (master, 20474a0) stopped a graph interval that was never running. Since commands now go out only when the running state changes, that queued nothing; the test ticks the interval once before stopping it. Folded into execution: the playheads of the intervals go through the telemetry.
  • Tests CMakeLists.txt and FaustDspTest.cpp: both sides' additions kept.

Checked

  • Full Debug build with tests (clang 19, Linux).
  • Tests: the whole suite, then every failure rerun at -j2 on this branch and on a master build of the same configuration. No test fails here that passes on master. What fails on both is GPU, media or PipeWire tests on a headless box, plus Avnd_regex (3/11) and one scriptable_dynamic_ports case, already failing on master.
  • One thing for the PR itself, not the rebase: TelemetryExecTest "updates stop with the execution-update setting" turns ExecutionUpdate off and only turns it back on after its checks pass. ctest keeps settings in build/test-home/config across tests and runs, so if a check fails under load the setting stays off. Every later test that needs execution updates then fails: playheads, telemetry, avnd control outputs, record_while_playing, device_enumeration_lifecycle. A guard that restores it on scope exit would avoid that.

The pre-rebase head was e0dffba0ea, and libossia#950's was f9e87ad5e0.

Since this rebase, master moved avendish to main (a1f6471, 4603c1c), so GitHub shows the avendish pointer as conflicting again. Nothing else conflicts, and e248fec merges into a1f6471 cleanly; rebasing #218 onto it and bumping the pointer here clears it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Lc7tYGHRn6TmaxMEfBTswW

jcelerier and others added 22 commits October 9, 2026 22:22
libossia now applies an interval's gain and pan once, in the outlet, for
every interval: the has_gain flag the bus status used to set is gone.
Buses set below unity in existing sessions will sound louder, since their
gain was applied twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
/out/main's gain is now a post-sum trim over every hardware output, applied
after the graph and before the actions, so the library preview stays out
of the mix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
The weights are swapped in, so the previous ones are freed with the
closure, off the audio thread. The gain/pan unit test now expects pan to be
left alone for signals wider than it: libossia no longer grows it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
Muting an interval goes through a command, from the interval header too,
and is saved in the document ("Muted"). An interval can also be soloed
("Soloed"): as long as one bus is soloed, the document silences every bus
that is not soloed and does not contain, or sit inside, a soloed bus. That
silence is computed, never saved, and reaches the execution as a mute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
AudioDevice::changed only fires when the whole device is rebuilt. Adding,
editing or removing a mapped or virtual port now emits portsChanged, so a
view of the ports can follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
Execution::Telemetry is where views ask for meters: what an audio outlet
carries after its gain, or every hardware input or output. The handles
outlive stops and starts. While the execution runs and the execution-update
setting is on, the engine owns an ossia::telemetry::arena, fed by the taps
and published at the document's coarse update rate, the same rate every
other execution feedback uses. Turning the setting off drops the arena and
detaches every tap while running.

makeExecutionTick is exported so that a test can drive the real tick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
It follows libossia, where such a generator made no channel and was silent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
Its inputs are silent and its outputs discarded, so a session without a
sound card, a headless test for instance, can still route to the hardware
channels and meter them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
It opened at -6 dB without ever sending it, so the master played at unity
while the toolbar said otherwise. It now starts from /out/main's gain and
follows it at the document's coarse update rate, since the mixer and
automation can change it too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
The right-click spin box changed the value but never sent sliderReleased,
so whoever commits on release left the command pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
score::LevelMeter draws a peak bar per channel in dBFS, with RMS, a peak
hold and a clip mark that stays until clicked. Its fall and hold are timed
on the wall clock, so it behaves the same at any update rate. It keeps the
widest channel count of the last seconds so that a signal whose width
changes does not make it jump, and draws channels too narrow for a bar as a
heat strip next to a bar of the loudest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
The tabs give way to one scrolling console of sections that can each be
shown or hidden: buses, hardware inputs and outputs, mapped and virtual
ports. The master, /out/main, stays pinned on the right.

A bus strip has a meter of what the bus carries after its gain, a channel
count, a dB fader, mute, solo and propagate, a balance and the output
address. Everything goes through commands and follows the model, so undo
and the interval header keep it in step. Selecting a strip selects its
interval and the score's selection highlights the strips. Device ports get
a fader and, for the hardware and the main ones, a meter.

Strips come in three widths. Meters are read through the telemetry arena,
at the document's coarse update rate, and not at all when execution updates
are off.

The exec test now parks the audio engine, whose actions would otherwise
run alongside the tick the test drives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
With the benchmark setting on, Execution::Telemetry gives every process
node of the running graph a bench tap, follows nodes as they come and go,
and reports each process's share of the real time, measured against the
buffer duration rather than against the whole tick, through the process's
benchmark signal. The mixer shows the sum for every process in a bus next
to its channel count.

The benchmark tick, the bench map slot and their metatype are gone: the
graph measures on every tick while benchmarking.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
A mapped input or output is a set of the card's channels, so its strip
shows those channels of the hardware meter, in the port's order. Strips
take the list of channels to show rather than a first channel and a count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
The VU Meter process drew what its "Levels" control outlet carried: a list
of boxed floats built on the audio thread, delivered lossily at the coarse
rate, with a peak hold counted in buffers. Its layer now asks the
execution's telemetry for a meter on the process's audio inlet and draws it
with the same LevelMeterState as the mixer, so peaks between two updates are
kept and the ballistics are timed on the wall clock. The Levels outlet
still carries the values for whatever is cabled to it.

LevelMeterState is the meter without a widget, for graphics items;
Execution::Telemetry can meter audio inlets as well as outlets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
An audio outlet now has an upmix: none, repeating the channels, or adding
silent ones, up to a channel count. It is saved, set with one undoable
step, and an interval hands it to its node. A bus strip offers it in its
context menu, which is also how a mono bus becomes pannable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
A bus's pan weights are one gain per channel: "Channel gains..." in its
context menu shows a fader for each of them, as many as the bus carries.
The balance now only moves the first two weights instead of replacing them
all.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
Changing a mapped port's channels or direction, or a virtual port's channel
count, took effect only at the next reconnection. The port is now changed
in place, as the same object, since running processes may hold a pointer
to it. Adding, editing and removing ports all happen while the audio
callback skips its tick, instead of under its feet. Turning a mapped port
into a virtual one or back still waits for a reconnection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
The Mapped and Virtual sections have a "+" that asks for a new port with the
audio protocol's own dialog and adds it, first showing the audio device in
the device explorer if the user had not added it there, as one undoable
step. A mapped or virtual port's strip can be edited or removed from its
context menu. Everything goes through the device explorer's commands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
Only the start and the stop of an interval are sent as commands, since
whether an interval is executing matters to the model; its position is
read from the telemetry at the interface's update rate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
The VU Meter also writes its levels in place instead of allocating a new
vector on every tick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
jcelerier and others added 16 commits October 9, 2026 22:22
What these processes show of the execution now comes at the telemetry's
update rate and stops with the execution-update setting. Faust reads the
values its node publishes instead of the DSP's zones, and the pattern
sequencer reads its step from an atomic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
Each tick sent a closure to the edition queue, which then read the control
outputs and MIDI buffers of voice 0 on the interface thread while the audio
thread wrote them, and after they had been reset. The control outputs now
go through a triple buffer read on the telemetry updates. The MIDI for the
plug-in's own interface is copied at the end of the tick, into a bounded
queue, and only while that interface is open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
…report back

The messages an avnd object or a script sends to its interface now follow
the execution-update setting, like every other execution feedback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
Execution::Telemetry::meterVirtualPort hands the port the address of a
tap and takes it back before the port goes away.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
Ports kept a pointer to the parameter of a removed node, and the execution
state an entry for it: removing a port from the mixer while a process wrote
to it crashed. When a device parameter that a port may point to is about to
be removed, the ports that point to it and the execution state drop it while
the audio callback skips its tick.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
Every strip has the same rows, which keep their place when empty: the
titles, channel counts, meters, readouts and controls of all the sections
and of the master are at the same heights. Titles share one style and
elide; the meter spans the fader's travel; section headers have one height;
the scale leaves out labels that would touch and no longer shades its
column; the strips keep room for the scroll bar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
The row of toggles and the section titles above the strips are replaced by
a vertical tab on the left of each section, like the folding sections of
the multi-window settings. The width of every strip moves to the tabs'
context menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
…he other way

The ports and the master no longer keep the room of the bus controls: their
meters and faders take it. The panel's minimum height follows the strips it
shows. The triangle of a tab points down when its section is folded, right
when it is open. An empty Buses section is only its tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
… the audio

Devices announce a subtree before removing it (nodeAboutToBeRemoved). The
telemetry lets go of the meters under it while their parameters still
exist, and when a process port may point there, the execution drops the
ports' addresses between two audio ticks: one wait of about a buffer for
the whole removal, and none when no port points there. The audio device is
followed in and out of the device list, and across its reconnections.

The audio device changes its ports by preparing them and swapping them in
between two ticks, instead of skipping audio callbacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
A run starts at the master gain. The telemetry finds a process's load and
a node's bench slot through maps instead of scanning every slot, and a bus
looks its processes up once a second instead of at every update.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
- Every audio outlet's gain, pan and upmix reach its running outlet, not
  only the intervals'; the model offered them on every outlet.
- Port faders and the toolbar volume only repaint when the gain changed.
- A bus strip updates only what a change shows: a fader drag no longer
  restyles its title at every move.
- Input strips show their levels after the gain they are read with.
- A meter tap is only made once it is known where it goes.
- Growing the telemetry arena no longer makes every meter flash off.
- The edit dialog of a port survives its strip being rebuilt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
…m before reads

The gain a port fader or the toolbar volume leaves on release is one undo
step (Audio::SetPortGain), kept as the node's audio-gain attribute and
restored when the document loads and when the device reconnects. Showing
the audio device in the explorer for it no longer reconnects the device,
which stopped the audio when it happened during playback: a reconnection
with the same engine and channels leaves the tree as it is.

Binary data written before mute, solo and upmix existed reads again: the
added fields are only read when present (DataStreamWriter::atDelimiterOrEnd).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
The deployment builds of Qt have no style sheets: setStyleSheet is not
declared at all there, and the AppImage build failed on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
GUIApplicationContext was only declared: the precompiled header hid it, a
build without one failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKbSZft9tvQ2sm9KeSchMX
@edumeneses

Copy link
Copy Markdown
Contributor

This is Edu's Claude assistant, posting on Edu's behalf.

Rebased once more, onto master 4b2f7f45ef. Master had moved avendish to main (a1f6471, 4603c1c), which was the only conflict. The 38 commits are unchanged except for the avendish bump in avnd: read the control values from the node's triple buffers. It now points at 4c2b41cd, which is avendish#210's commit on top of a1f6471 (cherry-picked cleanly, in celtera/avendish#218 again). libossia is unchanged (7e4f52c, ossia/libossia#950).

Full Debug build passes. I reran the telemetry, mixer, avnd, playhead, LV2 and audio tests. Only Avnd_regex, Avnd_point_tracker and Avnd_utilities fail, and they fail on master too.

Follows libossia's feature/mixer: an output fader now sets the level of
everything its channel plays, sent to /out/main, to a mapped port or straight
to /out/N; an input fader trims its channel for every reader. An input meter
is scaled per channel by what that channel is read with. The Inputs and
Outputs tabs say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lc7tYGHRn6TmaxMEfBTswW
@edumeneses

Copy link
Copy Markdown
Contributor

Hi JM, I pushed 08e951e to this branch. It goes with ossia/libossia#950 51236ae45: Edu wanted the /out/N and /in/N faders to act as channel faders for everything their channel gets, rather than only for what is sent straight to that address. The details are in this comment on #950.

Here, the commit:

  • scales the input meters per channel with read_gain;
  • updates the help text of the Inputs/Outputs tabs;
  • bumps the submodule.

The audio, port edit, telemetry, routing and outlet tests pass. If you want it split from #2302, tell us.

— Edu's Claude assistant

This branch has not been deployed

No deployments
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.

3 participants