Skip to content

Fix default_on_toggle and value_map decoding of named float structs - #197

Merged
jcelerier merged 2 commits into
mainfrom
fix/toggle-default-and-named-vec-decode
Aug 23, 2026
Merged

Fix default_on_toggle and value_map decoding of named float structs#197
jcelerier merged 2 commits into
mainfrom
fix/toggle-default-and-named-vec-decode

Conversation

@jcelerier

Copy link
Copy Markdown
Member

Two independent bugs found while building a process on top of this binding.

default_on_toggle defaulted to off

default_toggle and default_on_toggle were both toggle_setup{.init = false}, so the only thing separating them was the name. Any control declared halp::toggle<"...", halp::default_on_toggle> came up off.

It stayed invisible because a toggle reading false looks exactly like one the user turned off, and the binding initialises controls from range().init only in the host — a unit test constructing the object directly sees the same value either way.

A named all-float struct lost its value crossing ossia::value

to_ossia_value_impl tests for field names before vec-compatibility, so a struct with 2/3/4 float members and halp_field_names encodes as a value_map. The inbound path tested the two in the opposite order, took the vecNf shortcut, and called ossia::convert<vecNf>(map) — which returns zeroes.

So the round trip silently dropped the data: a std::vector of such structs (the ordinary shape for detector or tracker output) arrived as a list of correctly-sized, entirely zero elements. Downstream code saw the right number of entries with every field at 0.

Maps are now routed through the field-order decoder in both the nested and the top-level overload. Unnamed all-float structs still encode as vecNf and are unaffected, as is a bare vecNf sent by an external source.

Testing

Both directions are covered by a regression test in score (Tests/from_ossia_value_Test.cpp), which asserts the named struct round-trips, that an unnamed one still encodes as vec3f, and that a plain vec3f from an external sender still decodes into a named struct.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DnNVzm2dPA5iHbSYKrpzZj

jcelerier and others added 2 commits August 22, 2026 21:25
toggle_setup{.init = false} for both default_toggle and default_on_toggle,
so the only thing separating the two was their name: a control declared
halp::toggle<"...", halp::default_on_toggle> came up off.

Nothing caught it because a toggle that reads false is indistinguishable
from one the user turned off, and the binding initialises controls from
range().init in the host but not in a raw struct, so unit tests that
construct the object directly saw the same value either way.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DnNVzm2dPA5iHbSYKrpzZj
to_ossia_value_impl checks for field names before vec-compatibility, so a
struct with 2/3/4 float members and halp_field_names is *encoded* as a
value_map. The inbound path checked the two in the opposite order, took
the vecNf shortcut and called ossia::convert<vecNf>(map), which returns
zeroes.

The round trip therefore lost the value entirely: a std::vector of such
structs - the ordinary shape for detector output - arrived as a list of
correctly-sized, entirely zero elements. Route a map through the
field-order decoder instead, in both the nested and the top-level
overload.

Unnamed all-float structs still encode as vecNf and are unaffected, as is
a bare vecNf sent by an external source; the regression test in score
covers both directions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DnNVzm2dPA5iHbSYKrpzZj
@jcelerier
jcelerier merged commit 743120e into main Aug 23, 2026
5 of 23 checks passed
jcelerier added a commit to ossia/score that referenced this pull request Aug 23, 2026
libossia brings the filter, tracking and point-tracker primitives the new
processes are built on, the sound_utils and time_interval fixes, and
safe_isfinite (ossia/libossia#930).

Avendish brings the default_on_toggle fix - Entity To MIDI's Invert Axis is
declared with it and would otherwise come up off - and the value_map
decoding fix, without which a list of named float structs crosses the cable
as a list of zeroes (celtera/avendish#197).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DnNVzm2dPA5iHbSYKrpzZj
jcelerier added a commit to ossia/score that referenced this pull request Aug 23, 2026
libossia brings the filter, tracking and point-tracker primitives the new
processes are built on, the sound_utils and time_interval fixes, and
safe_isfinite (ossia/libossia#930).

Avendish brings the default_on_toggle fix - Entity To MIDI's Invert Axis is
declared with it and would otherwise come up off - and the value_map
decoding fix, without which a list of named float structs crosses the cable
as a list of zeroes (celtera/avendish#197).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DnNVzm2dPA5iHbSYKrpzZj
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.

1 participant