Main-thread UI and device owner
examples/tutorials/src/ui/mod.rs · 914 source lines
Read the chapters in source order. Select a numbered source line to expand its explanation; the line numbers and code match this snapshot exactly.
cargo run -p ravet-examples --bin midi-synth --locked -- --ui-test target/examples-ui-guideChapters
- Import the native and control-thread services lines 1–15
- Build an explicit device-capability record lines 16–61
- Validate the requested output configuration lines 62–102
- Validate channel-pair selection lines 103–121
- Own output, duplex or test rendering lines 122–147
- Keep UI state outside the callback lines 148–165
- Initialize and explicitly refresh inventories lines 166–238
- Stop and release native ownership lines 239–251
- Report a full control queue lines 252–263
- Start from validated settings lines 264–346
- Choose output-only or clocked duplex ownership lines 347–385
- Send the prepared patch before playback lines 386–414
- Dispatch and validate page messages lines 415–462
- Validate short MIDI at the bridge lines 463–475
- Inspect exact MIDI 2.0 fields lines 476–527
- Handle explicit device and mode actions lines 528–552
- Render a hardware-free UI probe lines 553–558
- Convert coherent words into presentation JSON lines 559–577
- Clean up and implement the native bridge lines 578–602
- Open the window with the default I/O settings lines 603–637
- Exercise all modes without device I/O lines 638–783
- Check uniform design-canvas scaling lines 784–821
- Verify settings opt-out and default behavior lines 822–870
- Check keyboard and numeric control gestures lines 871–892
- Check pointer-held notes and cancellation lines 893–914
Import the native and control-thread services
This module owns JSON, device selection, stream lifetime and the native window on the main thread. audio is the separate prepared owner. Rc/RefCell are for main-thread shared UI state; Arc hands coherent telemetry to the audio owner.
1//! macOS example window, main-thread UI/device ownership and bounded audio handoff.
Source note: macOS example window, main-thread UI/device ownership and bounded audio handoff.
Link to line 12mod audio;
Bring these module/type names into scope for “Import the native and control-thread services”; the surrounding chapter explains their responsibilities.
Link to line 23use crate::synth::{DEFAULT_VALUES, RANGES, SynthPatch};
Bring these module/type names into scope for “Import the native and control-thread services”; the surrounding chapter explains their responsibilities.
Link to line 34use audio::{Audio, Command, MAX_FRAMES, QUEUE, Routing, Shared};
Bring these module/type names into scope for “Import the native and control-thread services”; the surrounding chapter explains their responsibilities.
Link to line 45use cpal::traits::DeviceTrait;
Bring these module/type names into scope for “Import the native and control-thread services”; the surrounding chapter explains their responsibilities.
Link to line 56use ravet_device::{
Bring these module/type names into scope for “Import the native and control-thread services”; the surrounding chapter explains their responsibilities.
Link to line 67 ClockedDuplexOptions, ClockedDuplexStream, OutputStream, PreparedOutput, cpal,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 78 open_clocked_duplex, open_output,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 89};
Close the surrounding scope, value or argument list in “Import the native and control-thread services”.
Link to line 910use ravet_foundation::{Midi2Kind, Midi2Message, MidiMessage};
Bring these module/type names into scope for “Import the native and control-thread services”; the surrounding chapter explains their responsibilities.
Link to line 1011use ravet_webview::{Callbacks, StandaloneOptions, StandaloneWindow};
Bring these module/type names into scope for “Import the native and control-thread services”; the surrounding chapter explains their responsibilities.
Link to line 1112use serde_json::{Value, json};
Bring these module/type names into scope for “Import the native and control-thread services”; the surrounding chapter explains their responsibilities.
Link to line 1213use std::{cell::RefCell, rc::Rc, sync::Arc};
Bring these module/type names into scope for “Import the native and control-thread services”; the surrounding chapter explains their responsibilities.
Link to line 1314type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
Define a type alias so the following functions can use this complete result/error type by its shorter name.
Link to line 1415
Blank line separating the surrounding statements.
Link to line 15Build an explicit device-capability record
Filter default-channel f32 ranges. Form common candidate rates plus the device default, sort/deduplicate and retain supported values in 8–192 kHz. Keep candidate buffers supported by a range, including unknown negotiation. Report channels capped at 64. These labels are capabilities, not latency measurements.
16fn device_info(
Define device_info. Filter default-channel f32 ranges. Form common candidate rates plus the device default, sort/deduplicate and retain supported values in 8–192 kHz. Keep candidate buffers supported by a range, including unknown negotiation. Report channels capped at 64. These labels are capabilities, not latency measurements.
Link to line 1617 id: String,
Define or initialize id with the displayed type/value. Its ownership and use are described in “Build an explicit device-capability record”.
Link to line 1718 name: String,
Define or initialize name with the displayed type/value. Its ownership and use are described in “Build an explicit device-capability record”.
Link to line 1819 ranges: Vec<cpal::SupportedStreamConfigRange>,
Define or initialize ranges with the displayed type/value. Its ownership and use are described in “Build an explicit device-capability record”.
Link to line 1920 default: cpal::SupportedStreamConfig,
Define or initialize default with the displayed type/value. Its ownership and use are described in “Build an explicit device-capability record”.
Link to line 2021) -> Result<Value> {
Complete the function’s parameter list and specify the return type. A Result preserves the explicit success/error distinction.
Link to line 2122 let channels = default.channels();
Bind channels to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 2223 let ranges = ranges
Bind ranges to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 2324 .into_iter()
Consume the collection into an owning iterator; its elements are moved into the following transformation.
Link to line 2425 .filter(|r| r.sample_format() == cpal::SampleFormat::F32 && r.channels() == channels)
Keep only entries for which this predicate returns true.
Link to line 2526 .collect::<Vec<_>>();
Collect the iterator into an owned Vec. This may allocate and belongs to setup, offline fixtures or the main-thread UI path.
Link to line 2627 let mut rates = vec![
Bind mutable rates to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 2728 8000,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 2829 11025,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 2930 16000,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 3031 22050,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 3132 32000,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 3233 44100,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 3334 48000,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 3435 88200,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 3536 96000,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 3637 176400,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 3738 192000,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 3839 default.sample_rate(),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Build an explicit device-capability record” explanation above.
Link to line 3940 ];
Close the surrounding scope, value or argument list in “Build an explicit device-capability record”.
Link to line 4041 rates.sort_unstable();
Sort the candidate values in place; ordering of equal entries is irrelevant here.
Link to line 4142 rates.dedup();
Remove adjacent duplicates after sorting so each candidate appears once.
Link to line 4243 rates.retain(|rate| {
Filter this existing Vec in place by the supplied supported-value predicate.
Link to line 4344 (8000..=192000).contains(rate)
Assign the computed value to (8000... The right-hand expression supplies the new value for this step.
Link to line 4445 && ranges
Require this additional condition as well; the combined check succeeds only when all conditions are true.
Link to line 4546 .iter()
Borrow collection entries for iteration without moving or copying the whole collection.
Link to line 4647 .any(|r| r.min_sample_rate() <= *rate && *rate <= r.max_sample_rate())
Return true if any entry satisfies this predicate; stop at the first match.
Link to line 4748 });
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 4849 let buffers = [32, 64, 128, 256, 512, 1024, 2048, 4096]
Bind buffers to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 4950 .into_iter()
Consume the collection into an owning iterator; its elements are moved into the following transformation.
Link to line 5051 .filter(|frames| {
Keep only entries for which this predicate returns true.
Link to line 5152 ranges.iter().any(|r| match r.buffer_size() {
Borrow collection entries for iteration without moving or copying the whole collection.
Link to line 5253 cpal::SupportedBufferSize::Range { min, max } => min <= frames && frames <= max,
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 5354 cpal::SupportedBufferSize::Unknown => true,
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 5455 })
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 5556 })
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 5657 .collect::<Vec<_>>();
Collect the iterator into an owned Vec. This may allocate and belongs to setup, offline fixtures or the main-thread UI path.
Link to line 5758 Ok(
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 5859 json!({"id":id,"name":name,"channels":channels.min(64),"rates":rates,"default_rate":default.sample_rate(),"buffers":buffers}),
Build the main-thread presentation JSON from these named values; the audio owner publishes fixed words instead of serializing JSON.
Link to line 5960 )
Close the surrounding scope, value or argument list in “Build an explicit device-capability record”.
Link to line 6061}
Close the surrounding scope, value or argument list in “Build an explicit device-capability record”.
Link to line 61Validate the requested output configuration
Read unsigned rate/buffer fields, check bounds and match an available f32 configuration with the device’s default channel count. Buffer zero means device default; a positive value requests a fixed buffer. A requested buffer does not guarantee every callback has that length.
62fn selected_output_config(device: &cpal::Device, message: &Value) -> Result<cpal::StreamConfig> {
Define selected_output_config. Read unsigned rate/buffer fields, check bounds and match an available f32 configuration with the device’s default channel count. Buffer zero means device default; a positive value requests a fixed buffer. A requested buffer does not guarantee every callback has that length.
Link to line 6263 let default = device.default_output_config()?;
Bind default to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 6364 let rate = u32::try_from(
Bind rate to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 6465 message["sample_rate"]
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Validate the requested output configuration” explanation above.
Link to line 6566 .as_u64()
Accept a JSON unsigned integer. Missing, negative or incompatible values produce None for the subsequent validation.
Link to line 6667 .ok_or("Choose a sample rate")?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 6768 )?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 6869 let buffer = u32::try_from(
Bind buffer to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 6970 message["buffer_size"]
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Validate the requested output configuration” explanation above.
Link to line 7071 .as_u64()
Accept a JSON unsigned integer. Missing, negative or incompatible values produce None for the subsequent validation.
Link to line 7172 .ok_or("Choose a buffer size")?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 7273 )?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 7374 if !(8000..=192000).contains(&rate) || buffer > 65536 || default.channels() > 64 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate the requested output configuration”.
Link to line 7475 return Err("Unsupported output configuration".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 7576 }
Close the surrounding scope, value or argument list in “Validate the requested output configuration”.
Link to line 7677 let supported = device.supported_output_configs()?.any(|r| {
Bind supported to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 7778 r.sample_format() == cpal::SampleFormat::F32
Assign the computed value to r.sample_format(). The right-hand expression supplies the new value for this step.
Link to line 7879 && r.channels() == default.channels()
Require this additional condition as well; the combined check succeeds only when all conditions are true.
Link to line 7980 && r.min_sample_rate() <= rate
Require this additional condition as well; the combined check succeeds only when all conditions are true.
Link to line 8081 && rate <= r.max_sample_rate()
Require this additional condition as well; the combined check succeeds only when all conditions are true.
Link to line 8182 && (buffer == 0
Require this additional condition as well; the combined check succeeds only when all conditions are true.
Link to line 8283 || match r.buffer_size() {
Accept this alternative condition in the surrounding check; evaluation stops once the combined condition is true.
Link to line 8384 cpal::SupportedBufferSize::Range { min, max } => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 8485 *min <= buffer && buffer <= *max
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Validate the requested output configuration” explanation above.
Link to line 8586 }
Close the surrounding scope, value or argument list in “Validate the requested output configuration”.
Link to line 8687 cpal::SupportedBufferSize::Unknown => true,
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 8788 })
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 8889 });
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 8990 if !supported {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate the requested output configuration”.
Link to line 9091 return Err("Selected sample rate / buffer size is unavailable".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 9192 }
Close the surrounding scope, value or argument list in “Validate the requested output configuration”.
Link to line 9293 Ok(cpal::StreamConfig {
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 9394 channels: default.channels(),
Define or initialize channels with the displayed type/value. Its ownership and use are described in “Validate the requested output configuration”.
Link to line 9495 sample_rate: rate,
Define or initialize sample_rate with the displayed type/value. Its ownership and use are described in “Validate the requested output configuration”.
Link to line 9596 buffer_size: if buffer == 0 {
Define or initialize buffer_size with the displayed type/value. Its ownership and use are described in “Validate the requested output configuration”.
Link to line 9697 cpal::BufferSize::Default
Define or initialize cpal with the displayed type/value. Its ownership and use are described in “Validate the requested output configuration”.
Link to line 9798 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Validate the requested output configuration” explanation above.
Link to line 9899 cpal::BufferSize::Fixed(buffer)
Define or initialize cpal with the displayed type/value. Its ownership and use are described in “Validate the requested output configuration”.
Link to line 99100 },
Close the surrounding scope, value or argument list in “Validate the requested output configuration”.
Link to line 100101 })
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 101102}
Close the surrounding scope, value or argument list in “Validate the requested output configuration”.
Link to line 102Validate channel-pair selection
Require a nonempty list of at most 32 pairs. Pair starts must be even, unique, within the device and below 64. Mark the first and, if available, second channel. A final odd channel is allowed as a one-channel pair.
103fn channel_mask(pairs: &Value, channels: usize) -> Result<u64> {
Define channel_mask. Require a nonempty list of at most 32 pairs. Pair starts must be even, unique, within the device and below 64. Mark the first and, if available, second channel. A final odd channel is allowed as a one-channel pair.
Link to line 103104 let pairs = pairs
Bind pairs to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 104105 .as_array()
Require a JSON array and borrow its entries; incompatible JSON produces None.
Link to line 105106 .filter(|p| !p.is_empty() && p.len() <= 32)
Keep only entries for which this predicate returns true.
Link to line 106107 .ok_or("Select at least one channel pair")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 107108 let mut mask = 0u64;
Bind mutable mask to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 108109 for pair in pairs {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate channel-pair selection”.
Link to line 109110 let first = usize::try_from(pair.as_u64().ok_or("Invalid channel pair")?)?;
Bind first to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 110111 if first >= channels || first >= 64 || first % 2 != 0 || mask & (1u64 << first) != 0 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate channel-pair selection”.
Link to line 111112 return Err("Invalid or duplicate channel pair".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 112113 }
Close the surrounding scope, value or argument list in “Validate channel-pair selection”.
Link to line 113114 mask |= 1u64 << first;
Set the selected bits in mask. The right-hand expression supplies the new value for this step.
Link to line 114115 if first + 1 < channels {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate channel-pair selection”.
Link to line 115116 mask |= 1u64 << (first + 1);
Set the selected bits in mask. The right-hand expression supplies the new value for this step.
Link to line 116117 }
Close the surrounding scope, value or argument list in “Validate channel-pair selection”.
Link to line 117118 }
Close the surrounding scope, value or argument list in “Validate channel-pair selection”.
Link to line 118119 Ok(mask)
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 119120}
Close the surrounding scope, value or argument list in “Validate channel-pair selection”.
Link to line 120121
Blank line separating the surrounding statements.
Link to line 121Own output, duplex or test rendering
Running distinguishes a live output stream, a live clocked duplex stream and a hardware-free PreparedOutput. stop pauses native playback. errors inspects processor faults, panics and backend errors without inventing a successful recovery.
122enum Running {
Declare the state/type or implementation used by this chapter. Running distinguishes a live output stream, a live clocked duplex stream and a hardware-free PreparedOutput. stop pauses native playback. errors inspects processor faults, panics and backend errors without inventing a successful recovery.
Link to line 122123 Output(OutputStream),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Own output, duplex or test rendering” explanation above.
Link to line 123124 Duplex(ClockedDuplexStream),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Own output, duplex or test rendering” explanation above.
Link to line 124125 Test(Box<PreparedOutput<Audio>>),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Own output, duplex or test rendering” explanation above.
Link to line 125126}
Close the surrounding scope, value or argument list in “Own output, duplex or test rendering”.
Link to line 126127impl Running {
Declare the state/type or implementation used by this chapter. Running distinguishes a live output stream, a live clocked duplex stream and a hardware-free PreparedOutput. stop pauses native playback. errors inspects processor faults, panics and backend errors without inventing a successful recovery.
Link to line 127128 fn stop(&self) {
Define stop. Running distinguishes a live output stream, a live clocked duplex stream and a hardware-free PreparedOutput. stop pauses native playback. errors inspects processor faults, panics and backend errors without inventing a successful recovery.
Link to line 128129 match self {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Own output, duplex or test rendering”.
Link to line 129130 Self::Output(s) => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 130131 let _ = s.pause();
Bind _ to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 131132 }
Close the surrounding scope, value or argument list in “Own output, duplex or test rendering”.
Link to line 132133 Self::Duplex(s) => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 133134 let _ = s.pause();
Bind _ to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 134135 }
Close the surrounding scope, value or argument list in “Own output, duplex or test rendering”.
Link to line 135136 Self::Test(_) => {}
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 136137 }
Close the surrounding scope, value or argument list in “Own output, duplex or test rendering”.
Link to line 137138 }
Close the surrounding scope, value or argument list in “Own output, duplex or test rendering”.
Link to line 138139 fn errors(&self) -> bool {
Define errors. Running distinguishes a live output stream, a live clocked duplex stream and a hardware-free PreparedOutput. stop pauses native playback. errors inspects processor faults, panics and backend errors without inventing a successful recovery.
Link to line 139140 let s = match self {
Bind s to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 140141 Self::Output(s) => s.statistics(),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 141142 Self::Duplex(s) => s.output_statistics(),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 142143 Self::Test(s) => s.statistics(),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 143144 };
Close the surrounding scope, value or argument list in “Own output, duplex or test rendering”.
Link to line 144145 s.processor_faults != 0 || s.panics != 0 || s.backend_errors != 0
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Own output, duplex or test rendering” explanation above.
Link to line 145146 }
Close the surrounding scope, value or argument list in “Own output, duplex or test rendering”.
Link to line 146147}
Close the surrounding scope, value or argument list in “Own output, duplex or test rendering”.
Link to line 147Keep UI state outside the callback
State stores mode, control values, device inventories, command producer, running owner, MIDI streams, snapshot words and inspector packets. These allocating values stay on the main thread. Audio sees only prepared commands and the shared mailbox.
148struct State {
Declare the state/type or implementation used by this chapter. State stores mode, control values, device inventories, command producer, running owner, MIDI streams, snapshot words and inspector packets. These allocating values stay on the main thread. Audio sees only prepared commands and the shared mailbox.
Link to line 148149 mode: String,
Define or initialize mode with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 149150 values: [f32; 9],
Requested physical controls in the order documented for this processor.
Link to line 150151 delay: [f32; 5],
Define or initialize delay with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 151152 demo: bool,
Whether the effect input uses the synthetic demonstration source.
Link to line 152153 rate: f64,
Sample rate used to design this patch’s envelope and coefficients.
Link to line 153154 status: String,
Define or initialize status with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 154155 outputs: Vec<Value>,
Define or initialize outputs with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 155156 inputs: Vec<Value>,
Define or initialize inputs with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 156157 midis: Vec<Value>,
Define or initialize midis with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 157158 producer: Option<rtrb::Producer<Command>>,
Define or initialize producer with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 158159 running: Option<Running>,
Define or initialize running with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 159160 midi: Vec<ravet_midi_device::MidiInputStream>,
Prepared native input receivers and their last observed loss counts.
Link to line 160161 shared: Arc<Shared>,
Reference-counted mailbox and reset flag shared with the main-thread owner.
Link to line 161162 words: [u32; 80],
Define or initialize words with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 162163 test: bool,
Define or initialize test with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 163164 packets: Vec<String>,
Define or initialize packets with the displayed type/value. Its ownership and use are described in “Keep UI state outside the callback”.
Link to line 164165}
Close the surrounding scope, value or argument list in “Keep UI state outside the callback”.
Link to line 165Initialize and explicitly refresh inventories
new starts inactive with defaults and refreshes inventory. Test mode provides deterministic fake output/input/MIDI records. The MIDI 2.0 inspector avoids audio enumeration. Native enumeration maps stable IDs and supported channel/rate/buffer ranges for explicit user selection.
166impl State {
Declare the state/type or implementation used by this chapter. new starts inactive with defaults and refreshes inventory. Test mode provides deterministic fake output/input/MIDI records. The MIDI 2.0 inspector avoids audio enumeration. Native enumeration maps stable IDs and supported channel/rate/buffer ranges for explicit user selection.
Link to line 166167 fn new(mode: &str, test: bool) -> Self {
Define new. new starts inactive with defaults and refreshes inventory. Test mode provides deterministic fake output/input/MIDI records. The MIDI 2.0 inspector avoids audio enumeration. Native enumeration maps stable IDs and supported channel/rate/buffer ranges for explicit user selection.
Link to line 167168 let mut state = Self {
Bind mutable state to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 168169 mode: mode.to_owned(),
Define or initialize mode with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 169170 values: DEFAULT_VALUES,
Requested physical controls in the order documented for this processor.
Link to line 170171 delay: crate::delay::DEFAULT_VALUES,
Define or initialize delay with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 171172 demo: true,
Whether the effect input uses the synthetic demonstration source.
Link to line 172173 rate: 48_000.,
Sample rate used to design this patch’s envelope and coefficients.
Link to line 173174 status: "Ready · choose an output and press Start".into(),
Define or initialize status with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 174175 outputs: Vec::new(),
Define or initialize outputs with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 175176 inputs: Vec::new(),
Define or initialize inputs with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 176177 midis: Vec::new(),
Define or initialize midis with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 177178 producer: None,
Define or initialize producer with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 178179 running: None,
Define or initialize running with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 179180 midi: Vec::new(),
Prepared native input receivers and their last observed loss counts.
Link to line 180181 shared: Shared::new(),
Reference-counted mailbox and reset flag shared with the main-thread owner.
Link to line 181182 words: [0; 80],
Define or initialize words with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 182183 test,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 183184 packets: Vec::new(),
Define or initialize packets with the displayed type/value. Its ownership and use are described in “Initialize and explicitly refresh inventories”.
Link to line 184185 };
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 185186 if let Err(e) = state.refresh() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Initialize and explicitly refresh inventories”.
Link to line 186187 state.status = e.to_string();
Assign the computed value to state.status. The right-hand expression supplies the new value for this step.
Link to line 187188 }
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 188189 state
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Initialize and explicitly refresh inventories” explanation above.
Link to line 189190 }
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 190191 fn refresh(&mut self) -> Result<()> {
Define refresh. new starts inactive with defaults and refreshes inventory. Test mode provides deterministic fake output/input/MIDI records. The MIDI 2.0 inspector avoids audio enumeration. Native enumeration maps stable IDs and supported channel/rate/buffer ranges for explicit user selection.
Link to line 191192 if self.test {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Initialize and explicitly refresh inventories”.
Link to line 192193 self.outputs = vec![
Assign the computed value to self.outputs. The right-hand expression supplies the new value for this step.
Link to line 193194 json!({"id":"test-output","name":"Offline UI fixture","channels":6,"rates":[44100,48000,96000],"default_rate":48000,"buffers":[64,128,256,512,1024]}),
Build the main-thread presentation JSON from these named values; the audio owner publishes fixed words instead of serializing JSON.
Link to line 194195 ];
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 195196 self.inputs = vec![
Assign the computed value to self.inputs. The right-hand expression supplies the new value for this step.
Link to line 196197 json!({"id":"test-input","name":"Offline capture fixture","channels":4,"rates":[48000],"default_rate":48000,"buffers":[128,256]}),
Build the main-thread presentation JSON from these named values; the audio owner publishes fixed words instead of serializing JSON.
Link to line 197198 ];
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 198199 self.midis = vec![
Assign the computed value to self.midis. The right-hand expression supplies the new value for this step.
Link to line 199200 json!({"id":"midi-a","name":"Fixture keyboard"}),
Build the main-thread presentation JSON from these named values; the audio owner publishes fixed words instead of serializing JSON.
Link to line 200201 json!({"id":"midi-b","name":"Fixture MPE controller"}),
Build the main-thread presentation JSON from these named values; the audio owner publishes fixed words instead of serializing JSON.
Link to line 201202 ];
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 202203 return Ok(());
Return this result to the caller; the remaining statements in the function are skipped.
Link to line 203204 }
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 204205 if self.mode == "midi2" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Initialize and explicitly refresh inventories”.
Link to line 205206 return Ok(());
Return this result to the caller; the remaining statements in the function are skipped.
Link to line 206207 }
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 207208 self.outputs = ravet_device::output_devices()?
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 208209 .into_iter()
Consume the collection into an owning iterator; its elements are moved into the following transformation.
Link to line 209210 .map(|d| {
Transform each iterator entry, or the successful value of an Option/Result, using the supplied closure.
Link to line 210211 let device =
Bind device to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 211212 ravet_device::output_device(Some(&d.id))?.ok_or("Output disappeared")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 212213 device_info(
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Initialize and explicitly refresh inventories” explanation above.
Link to line 213214 d.id,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Initialize and explicitly refresh inventories” explanation above.
Link to line 214215 d.name,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Initialize and explicitly refresh inventories” explanation above.
Link to line 215216 d.configurations,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Initialize and explicitly refresh inventories” explanation above.
Link to line 216217 device.default_output_config()?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 217218 )
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 218219 })
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 219220 .collect::<Result<Vec<_>>>()?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 220221 self.inputs = ravet_device::input_devices()?
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 221222 .into_iter()
Consume the collection into an owning iterator; its elements are moved into the following transformation.
Link to line 222223 .map(|d| {
Transform each iterator entry, or the successful value of an Option/Result, using the supplied closure.
Link to line 223224 let device = ravet_device::input_device(Some(&d.id))?.ok_or("Input disappeared")?;
Bind device to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 224225 device_info(
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Initialize and explicitly refresh inventories” explanation above.
Link to line 225226 d.id,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Initialize and explicitly refresh inventories” explanation above.
Link to line 226227 d.name,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Initialize and explicitly refresh inventories” explanation above.
Link to line 227228 d.configurations,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Initialize and explicitly refresh inventories” explanation above.
Link to line 228229 device.default_input_config()?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 229230 )
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 230231 })
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 231232 .collect::<Result<Vec<_>>>()?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 232233 self.midis = ravet_midi_device::input_ports()?
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 233234 .into_iter()
Consume the collection into an owning iterator; its elements are moved into the following transformation.
Link to line 234235 .map(|p| json!({"id":p.id,"name":p.name}))
Transform each iterator entry, or the successful value of an Option/Result, using the supplied closure.
Link to line 235236 .collect();
Call the displayed operation with these arguments as the next step in “Initialize and explicitly refresh inventories”. The chapter describes its role and validation.
Link to line 236237 Ok(())
Report successful completion without returning a payload.
Link to line 237238 }
Close the surrounding scope, value or argument list in “Initialize and explicitly refresh inventories”.
Link to line 238Stop and release native ownership
Take/pause/drop the running stream, close MIDI inputs, remove the producer and replace telemetry with empty shared state. The selected physical controls remain in State for a subsequent start.
239 fn stop(&mut self) {
Define stop. Take/pause/drop the running stream, close MIDI inputs, remove the producer and replace telemetry with empty shared state. The selected physical controls remain in State for a subsequent start.
Link to line 239240 if let Some(running) = self.running.take() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Stop and release native ownership”.
Link to line 240241 running.stop();
Call the displayed operation with these arguments as the next step in “Stop and release native ownership”. The chapter describes its role and validation.
Link to line 241242 drop(running);
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 242243 }
Close the surrounding scope, value or argument list in “Stop and release native ownership”.
Link to line 243244 for midi in self.midi.drain(..) {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Stop and release native ownership”.
Link to line 244245 drop(midi.close());
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 245246 }
Close the surrounding scope, value or argument list in “Stop and release native ownership”.
Link to line 246247 self.producer = None;
Assign the computed value to self.producer. The right-hand expression supplies the new value for this step.
Link to line 247248 self.words = [0; 80];
Assign the computed value to self.words. The right-hand expression supplies the new value for this step.
Link to line 248249 self.shared = Shared::new();
Assign the computed value to self.shared. The right-hand expression supplies the new value for this step.
Link to line 249250 self.status = "Stopped".into();
Assign the computed value to self.status. The right-hand expression supplies the new value for this step.
Link to line 250251 }
Close the surrounding scope, value or argument list in “Stop and release native ownership”.
Link to line 251Report a full control queue
Reject note/control delivery while stopped. A full queue atomically requests a panic/reset and returns a retryable UI error. It does not claim the rejected command reached the processor.
252 fn push(&mut self, command: Command) -> Result<()> {
Define push. Reject note/control delivery while stopped. A full queue atomically requests a panic/reset and returns a retryable UI error. It does not claim the rejected command reached the processor.
Link to line 252253 let Some(producer) = &mut self.producer else {
Bind Some to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 253254 return Err("Press Start before playing notes".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 254255 };
Close the surrounding scope, value or argument list in “Report a full control queue”.
Link to line 255256 if producer.push(command).is_err() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Report a full control queue”.
Link to line 256257 self.shared
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Report a full control queue” explanation above.
Link to line 257258 .panic
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Report a full control queue” explanation above.
Link to line 258259 .store(true, std::sync::atomic::Ordering::Release);
Publish the new atomic flag/value using the specified memory ordering.
Link to line 259260 return Err("Control queue full · notes cleared; retry the control".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 260261 }
Close the surrounding scope, value or argument list in “Report a full control queue”.
Link to line 261262 Ok(())
Report successful completion without returning a payload.
Link to line 262263 }
Close the surrounding scope, value or argument list in “Report a full control queue”.
Link to line 263Start from validated settings
Stop the old session before selecting a new output. Create the bounded command ring. Test mode constructs fake prepared output. Native mode validates f32 output/routing, opens at most 16 unique MIDI inputs for a synth and optionally selects a default-f32 input.
264 fn start(&mut self, message: &Value) -> Result<()> {
Define start. Stop the old session before selecting a new output. Create the bounded command ring. Test mode constructs fake prepared output. Native mode validates f32 output/routing, opens at most 16 unique MIDI inputs for a synth and optionally selects a default-f32 input.
Link to line 264265 self.stop();
Call the displayed operation with these arguments as the next step in “Start from validated settings”. The chapter describes its role and validation.
Link to line 265266 let synth = self.mode != "effect";
Bind synth to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 266267 let output_id = message["output"]
Bind output_id to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 267268 .as_str()
Require a JSON string and borrow its text; incompatible JSON produces None.
Link to line 268269 .filter(|s| !s.is_empty())
Keep only entries for which this predicate returns true.
Link to line 269270 .ok_or("Choose an audio output")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 270271 let source = message["input"].as_str().unwrap_or("");
Bind source to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 271272 let demo = !synth && self.demo;
Bind demo to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 272273 let (producer, consumer) = rtrb::RingBuffer::new(QUEUE);
Call the displayed operation with these arguments as the next step in “Start from validated settings”. The chapter describes its role and validation.
Link to line 273274 self.producer = Some(producer);
Assign the computed value to self.producer. The right-hand expression supplies the new value for this step.
Link to line 274275 let result = (|| -> Result<Running> {
Bind result to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 275276 if self.test {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Start from validated settings”.
Link to line 276277 self.rate = message["sample_rate"].as_u64().unwrap_or(48000) as f64;
Accept a JSON unsigned integer. Missing, negative or incompatible values produce None for the subsequent validation.
Link to line 277278 if ![44100., 48000., 96000.].contains(&self.rate) {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Start from validated settings”.
Link to line 278279 return Err("Unsupported fixture sample rate".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 279280 }
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 280281 let routing = Routing {
Bind routing to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 281282 input: 3,
Select input channels zero and one: bitmask 3 is binary 11.
Link to line 282283 output: channel_mask(&message["output_pairs"], 6)?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 283284 };
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 284285 let audio = Audio::new(
Bind audio to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 285286 synth,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 286287 demo,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 287288 consumer,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 288289 Vec::new(),
Define or initialize Vec with the displayed type/value. Its ownership and use are described in “Start from validated settings”.
Link to line 289290 self.shared.clone(),
Clone this value. Fixed arrays copy their entries; owned strings/vectors may allocate and remain outside the callback.
Link to line 290291 routing,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 291292 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 292293 return Ok(Running::Test(Box::new(PreparedOutput::new(
Return this result to the caller; the remaining statements in the function are skipped.
Link to line 293294 audio,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 294295 self.rate as u32,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Start from validated settings” explanation above.
Link to line 295296 6,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 296297 MAX_FRAMES,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 297298 )?)));
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 298299 }
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 299300 let output = ravet_device::output_device(Some(output_id))?
Bind output to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 300301 .ok_or("Selected output is unavailable")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 301302 let config = selected_output_config(&output, message)?;
Bind config to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 302303 self.rate = f64::from(config.sample_rate);
Assign the computed value to self.rate. The right-hand expression supplies the new value for this step.
Link to line 303304 let mut receivers = Vec::new();
Bind mutable receivers to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 304305 if synth {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Start from validated settings”.
Link to line 305306 let ids = message["midis"]
Bind ids to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 306307 .as_array()
Require a JSON array and borrow its entries; incompatible JSON produces None.
Link to line 307308 .ok_or("MIDI inputs must be a list")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 308309 if ids.len() > 16 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Start from validated settings”.
Link to line 309310 return Err("Select at most 16 MIDI inputs".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 310311 }
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 311312 let mut unique = std::collections::BTreeSet::new();
Bind mutable unique to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 312313 for value in ids {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Start from validated settings”.
Link to line 313314 let id = value.as_str().ok_or("Invalid MIDI input ID")?;
Bind id to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 314315 if !unique.insert(id) {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Start from validated settings”.
Link to line 315316 return Err("Duplicate MIDI input".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 316317 }
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 317318 let (stream, receiver) = ravet_midi_device::open_input(id, 256)?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 318319 self.midi.push(stream);
Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.
Link to line 319320 receivers.push(receiver);
Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.
Link to line 320321 }
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 321322 }
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 322323 let output_mask = channel_mask(&message["output_pairs"], usize::from(config.channels))?;
Bind output_mask to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 323324 let input = if !source.is_empty() {
Bind input to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 324325 Some(
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Start from validated settings” explanation above.
Link to line 325326 ravet_device::input_device(Some(source))?
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 326327 .ok_or("Selected input is unavailable")?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 327328 )
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 328329 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Start from validated settings” explanation above.
Link to line 329330 None
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Start from validated settings” explanation above.
Link to line 330331 };
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 331332 let input_config = input
Bind input_config to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 332333 .as_ref()
Borrow the contained value without taking ownership; an absent Option stays absent.
Link to line 333334 .map(|device| device.default_input_config())
Transform each iterator entry, or the successful value of an Option/Result, using the supplied closure.
Link to line 334335 .transpose()?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 335336 if input_config
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Start from validated settings”.
Link to line 336337 .as_ref()
Borrow the contained value without taking ownership; an absent Option stays absent.
Link to line 337338 .is_some_and(|c| c.sample_format() != cpal::SampleFormat::F32)
Call the displayed operation with these arguments as the next step in “Start from validated settings”. The chapter describes its role and validation.
Link to line 338339 {
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 339340 return Err("Selected input's default format must be f32".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 340341 }
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 341342 let input_mask = if let Some(c) = &input_config {
Bind input_mask to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 342343 channel_mask(&message["input_pairs"], usize::from(c.channels()))?
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 343344 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Start from validated settings” explanation above.
Link to line 344345 3
Supply this literal numeric entry to the array or argument list being constructed. Its units/addressing follow the containing fixture or configuration.
Link to line 345346 };
Close the surrounding scope, value or argument list in “Start from validated settings”.
Link to line 346Choose output-only or clocked duplex ownership
Pass selected routing, prepared MIDI receivers and shared telemetry into Audio. A selected input uses open_clocked_duplex with a 512-frame prepared bound; output-only uses open_output. Any setup error runs cleanup before returning.
347 let audio = Audio::new(
Bind audio to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 347348 synth,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 348349 demo,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 349350 consumer,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 350351 receivers,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 351352 self.shared.clone(),
Clone this value. Fixed arrays copy their entries; owned strings/vectors may allocate and remain outside the callback.
Link to line 352353 Routing {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Choose output-only or clocked duplex ownership” explanation above.
Link to line 353354 input: input_mask,
Define or initialize input with the displayed type/value. Its ownership and use are described in “Choose output-only or clocked duplex ownership”.
Link to line 354355 output: output_mask,
Define or initialize output with the displayed type/value. Its ownership and use are described in “Choose output-only or clocked duplex ownership”.
Link to line 355356 },
Close the surrounding scope, value or argument list in “Choose output-only or clocked duplex ownership”.
Link to line 356357 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 357358 if let Some(input) = input {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Choose output-only or clocked duplex ownership”.
Link to line 358359 let input_config = input_config.expect("selected input config");
Bind input_config to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 359360 let options = ClockedDuplexOptions {
Bind options to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 360361 maximum_frames: MAX_FRAMES,
Define or initialize maximum_frames with the displayed type/value. Its ownership and use are described in “Choose output-only or clocked duplex ownership”.
Link to line 361362 ..ClockedDuplexOptions::default()
Call the displayed operation with these arguments as the next step in “Choose output-only or clocked duplex ownership”. The chapter describes its role and validation.
Link to line 362363 };
Close the surrounding scope, value or argument list in “Choose output-only or clocked duplex ownership”.
Link to line 363364 Ok(Running::Duplex(open_clocked_duplex(
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 364365 &input,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Choose output-only or clocked duplex ownership” explanation above.
Link to line 365366 &output,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Choose output-only or clocked duplex ownership” explanation above.
Link to line 366367 input_config.config(),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Choose output-only or clocked duplex ownership” explanation above.
Link to line 367368 config,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 368369 options.clock.capacity_frames,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Choose output-only or clocked duplex ownership” explanation above.
Link to line 369370 audio,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 370371 options,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 371372 )?))
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 372373 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Choose output-only or clocked duplex ownership” explanation above.
Link to line 373374 Ok(Running::Output(open_output(
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 374375 &output, config, MAX_FRAMES, audio,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Choose output-only or clocked duplex ownership” explanation above.
Link to line 375376 )?))
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 376377 }
Close the surrounding scope, value or argument list in “Choose output-only or clocked duplex ownership”.
Link to line 377378 })();
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Choose output-only or clocked duplex ownership” explanation above.
Link to line 378379 match result {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Choose output-only or clocked duplex ownership”.
Link to line 379380 Ok(r) => self.running = Some(r),
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 380381 Err(e) => {
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 381382 self.stop();
Call the displayed operation with these arguments as the next step in “Choose output-only or clocked duplex ownership”. The chapter describes its role and validation.
Link to line 382383 return Err(e);
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 383384 }
Close the surrounding scope, value or argument list in “Choose output-only or clocked duplex ownership”.
Link to line 384385 }
Close the surrounding scope, value or argument list in “Choose output-only or clocked duplex ownership”.
Link to line 385Send the prepared patch before playback
Queue a rate-matched synth patch or complete delay controls. MPE mode also queues lower-zone RPN negotiation. Request playback only after setup and queued initial controls succeed. Play failure cleans up ownership; success updates the status string.
386 if synth {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Send the prepared patch before playback”.
Link to line 386387 self.push(Command::Patch(SynthPatch::new(self.rate, self.values)?))?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 387388 if self.mode == "mpe" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Send the prepared patch before playback”.
Link to line 388389 for bytes in [
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Send the prepared patch before playback”.
Link to line 389390 [0xb0, 101, 0],
Set the RPN most-significant selector to zero on master channel 0. The next selector identifies the specific RPN.
Link to line 390391 [0xb0, 100, 6],
Select RPN 6, the MPE zone configuration, on the lower-zone master channel.
Link to line 391392 [0xb0, 6, 2],
Use Data Entry to request two lower-zone member channels, 1 and 2.
Link to line 392393 [0xb0, 101, 127],
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Send the prepared patch before playback” explanation above.
Link to line 393394 [0xb0, 100, 127],
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Send the prepared patch before playback” explanation above.
Link to line 394395 ] {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Send the prepared patch before playback” explanation above.
Link to line 395396 self.push(Command::Midi(MidiMessage::from_bytes(&bytes).expect("RPN")))?;
Require the invariant “RPN”. expect panics if it is broken; external inputs must be validated before relying on it.
Link to line 396397 }
Close the surrounding scope, value or argument list in “Send the prepared patch before playback”.
Link to line 397398 }
Close the surrounding scope, value or argument list in “Send the prepared patch before playback”.
Link to line 398399 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Send the prepared patch before playback” explanation above.
Link to line 399400 self.push(Command::Delay(self.delay))?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 400401 }
Close the surrounding scope, value or argument list in “Send the prepared patch before playback”.
Link to line 401402 let play = match self.running.as_ref().expect("opened stream") {
Bind play to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 402403 Running::Output(s) => s.play().map_err(|e| e.into()),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 403404 Running::Duplex(s) => s.play().map_err(|e| e.into()),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 404405 Running::Test(_) => Ok(()),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 405406 };
Close the surrounding scope, value or argument list in “Send the prepared patch before playback”.
Link to line 406407 if let Err(e) = play {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Send the prepared patch before playback”.
Link to line 407408 self.stop();
Call the displayed operation with these arguments as the next step in “Send the prepared patch before playback”. The chapter describes its role and validation.
Link to line 408409 return Err(e);
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 409410 }
Close the surrounding scope, value or argument list in “Send the prepared patch before playback”.
Link to line 410411
Blank line separating the surrounding statements.
Link to line 411412 self.status = format!("Running · {} Hz · selected channels", self.rate);
Assign the computed value to self.status. The right-hand expression supplies the new value for this step.
Link to line 412413 Ok(())
Report successful completion without returning a payload.
Link to line 413414 }
Close the surrounding scope, value or argument list in “Send the prepared patch before playback”.
Link to line 414Dispatch and validate page messages
begin/end mark gesture boundaries but need no separate action here. edit/value must contain a finite physical value. Candidate delay/synth patches validate before UI values commit; only a running session queues a prepared command. Effect control 6 selects the demo source.
415 fn handle(&mut self, message: &Value) -> Result<()> {
Define handle. begin/end mark gesture boundaries but need no separate action here. edit/value must contain a finite physical value. Candidate delay/synth patches validate before UI values commit; only a running session queues a prepared command. Effect control 6 selects the demo source.
Link to line 415416 match message["type"].as_str().ok_or("Missing message type")? {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Dispatch and validate page messages”.
Link to line 416417 "begin" | "end" => {}
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 417418 "edit" | "value" => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 418419 let id = message["id"].as_u64().ok_or("Invalid control ID")?;
Bind id to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 419420 let value = message["value"]
Bind value to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 420421 .as_f64()
Read a JSON numeric value as f64; separate bounds/finite checks still determine whether the control is acceptable.
Link to line 421422 .filter(|v| v.is_finite())
Keep only entries for which this predicate returns true.
Link to line 422423 .ok_or("Invalid control value")? as f32;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 423424 if self.mode == "effect" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Dispatch and validate page messages”.
Link to line 424425 if id == 6 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Dispatch and validate page messages”.
Link to line 425426 if value != 0. && value != 1. {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Dispatch and validate page messages”.
Link to line 426427 return Err("Invalid demo selection".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 427428 }
Close the surrounding scope, value or argument list in “Dispatch and validate page messages”.
Link to line 428429 if self.running.is_some() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Dispatch and validate page messages”.
Link to line 429430 self.push(Command::Demo(value == 1.))?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 430431 }
Close the surrounding scope, value or argument list in “Dispatch and validate page messages”.
Link to line 431432 self.demo = value == 1.;
Assign the computed value to self.demo. The right-hand expression supplies the new value for this step.
Link to line 432433 return Ok(());
Return this result to the caller; the remaining statements in the function are skipped.
Link to line 433434 }
Close the surrounding scope, value or argument list in “Dispatch and validate page messages”.
Link to line 434435 let index = usize::try_from(id)
Bind index to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 435436 .ok()
Call the displayed operation with these arguments as the next step in “Dispatch and validate page messages”. The chapter describes its role and validation.
Link to line 436437 .and_then(|id| id.checked_sub(1))
Call the displayed operation with these arguments as the next step in “Dispatch and validate page messages”. The chapter describes its role and validation.
Link to line 437438 .filter(|i| *i < 5)
Keep only entries for which this predicate returns true.
Link to line 438439 .ok_or("Invalid effect control")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 439440 let mut values = self.delay;
Bind mutable values to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 440441 values[index] = value;
Assign the computed value to values[index]. The right-hand expression supplies the new value for this step.
Link to line 441442 let mut validation = crate::delay::DelayProcessor::default();
Bind mutable validation to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 442443 validation.set_controls(values)?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 443444 if self.running.is_some() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Dispatch and validate page messages”.
Link to line 444445 self.push(Command::Delay(values))?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 445446 }
Close the surrounding scope, value or argument list in “Dispatch and validate page messages”.
Link to line 446447 self.delay = values;
Assign the computed value to self.delay. The right-hand expression supplies the new value for this step.
Link to line 447448 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Dispatch and validate page messages” explanation above.
Link to line 448449 let index = usize::try_from(id)
Bind index to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 449450 .ok()
Call the displayed operation with these arguments as the next step in “Dispatch and validate page messages”. The chapter describes its role and validation.
Link to line 450451 .and_then(|id| id.checked_sub(1))
Call the displayed operation with these arguments as the next step in “Dispatch and validate page messages”. The chapter describes its role and validation.
Link to line 451452 .filter(|i| *i < 9)
Keep only entries for which this predicate returns true.
Link to line 452453 .ok_or("Unknown synth control")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 453454 let mut values = self.values;
Copy the requested control array into a mutable candidate. Fixed-array copying does not allocate.
Link to line 454455 values[index] = value;
Assign the computed value to values[index]. The right-hand expression supplies the new value for this step.
Link to line 455456 let patch = SynthPatch::new(self.rate, values)?;
Bind patch to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 456457 if self.running.is_some() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Dispatch and validate page messages”.
Link to line 457458 self.push(Command::Patch(patch))?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 458459 }
Close the surrounding scope, value or argument list in “Dispatch and validate page messages”.
Link to line 459460 self.values = values;
Commit the validated whole control array. Validation above completes before this assignment.
Link to line 460461 }
Close the surrounding scope, value or argument list in “Dispatch and validate page messages”.
Link to line 461462 }
Close the surrounding scope, value or argument list in “Dispatch and validate page messages”.
Link to line 462Validate short MIDI at the bridge
Require at most three unsigned byte values, convert them safely to u8 and validate message shape with MidiMessage::from_bytes. Queue the typed result; raw browser arrays never reach the DSP unchecked.
463 "midi" => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 463464 let bytes = message["bytes"]
Bind bytes to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 464465 .as_array()
Require a JSON array and borrow its entries; incompatible JSON produces None.
Link to line 465466 .filter(|b| b.len() <= 3)
Keep only entries for which this predicate returns true.
Link to line 466467 .ok_or("Invalid MIDI bytes")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 467468 let mut data = [0; 3];
Bind mutable data to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 468469 for (i, value) in bytes.iter().enumerate() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate short MIDI at the bridge”.
Link to line 469470 data[i] = u8::try_from(value.as_u64().ok_or("Invalid MIDI byte")?)?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 470471 }
Close the surrounding scope, value or argument list in “Validate short MIDI at the bridge”.
Link to line 471472 let midi = MidiMessage::from_bytes(&data[..bytes.len()])
Bind midi to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 472473 .map_err(|_| "Invalid MIDI message")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 473474 self.push(Command::Midi(midi))?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 474475 }
Close the surrounding scope, value or argument list in “Validate short MIDI at the bridge”.
Link to line 475Inspect exact MIDI 2.0 fields
Validate group/channel/key/velocity/expression against their full bounds. Choose NoteOn, NoteOff, PerNotePitchBend or PolyPressure, encode then decode a typed packet, and retain at most 16 printable packet records. This path does not route MIDI 2.0 into synthesis.
476 "packet" => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 476477 let field = |name: &str, max: u64| -> Result<u64> {
Bind field to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 477478 message[name]
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Inspect exact MIDI 2.0 fields” explanation above.
Link to line 478479 .as_u64()
Accept a JSON unsigned integer. Missing, negative or incompatible values produce None for the subsequent validation.
Link to line 479480 .filter(|n| *n <= max)
Keep only entries for which this predicate returns true.
Link to line 480481 .ok_or_else(|| format!("Invalid MIDI 2.0 {name}").into())
Call the displayed operation with these arguments as the next step in “Inspect exact MIDI 2.0 fields”. The chapter describes its role and validation.
Link to line 481482 };
Close the surrounding scope, value or argument list in “Inspect exact MIDI 2.0 fields”.
Link to line 482483 let group = field("group", 15)? as u8;
Bind group to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 483484 let channel = field("channel", 15)? as u8;
Bind channel to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 484485 let key = field("key", 127)? as u8;
Bind key to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 485486 let kind = match message["kind"].as_str() {
Bind kind to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 486487 Some("on") => Midi2Kind::NoteOn {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 487488 key,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 488489 velocity: field("velocity", 65535)? as u16,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 489490 attribute_type: 0,
Define or initialize attribute_type with the displayed type/value. Its ownership and use are described in “Inspect exact MIDI 2.0 fields”.
Link to line 490491 attribute: 0,
Define or initialize attribute with the displayed type/value. Its ownership and use are described in “Inspect exact MIDI 2.0 fields”.
Link to line 491492 },
Close the surrounding scope, value or argument list in “Inspect exact MIDI 2.0 fields”.
Link to line 492493 Some("off") => Midi2Kind::NoteOff {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 493494 key,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 494495 velocity: field("velocity", 65535)? as u16,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 495496 attribute_type: 0,
Define or initialize attribute_type with the displayed type/value. Its ownership and use are described in “Inspect exact MIDI 2.0 fields”.
Link to line 496497 attribute: 0,
Define or initialize attribute with the displayed type/value. Its ownership and use are described in “Inspect exact MIDI 2.0 fields”.
Link to line 497498 },
Close the surrounding scope, value or argument list in “Inspect exact MIDI 2.0 fields”.
Link to line 498499 Some("bend") => Midi2Kind::PerNotePitchBend {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 499500 key,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 500501 value: field("expression", u32::MAX as u64)? as u32,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 501502 },
Close the surrounding scope, value or argument list in “Inspect exact MIDI 2.0 fields”.
Link to line 502503 Some("pressure") => Midi2Kind::PolyPressure {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 503504 key,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 504505 value: field("expression", u32::MAX as u64)? as u32,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 505506 },
Close the surrounding scope, value or argument list in “Inspect exact MIDI 2.0 fields”.
Link to line 506507 _ => return Err("Unknown MIDI 2.0 kind".into()),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 507508 };
Close the surrounding scope, value or argument list in “Inspect exact MIDI 2.0 fields”.
Link to line 508509 let typed = Midi2Message::new(group, channel, kind)
Bind typed to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 509510 .map_err(|_| "Invalid MIDI 2.0 fields")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 510511 let packet = typed.packet();
Bind packet to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 511512 let decoded = Midi2Message::from_packet(packet).map_err(|_| "Invalid packet")?;
Bind decoded to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 512513 let words = packet
Bind words to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 513514 .as_words()
Call the displayed operation with these arguments as the next step in “Inspect exact MIDI 2.0 fields”. The chapter describes its role and validation.
Link to line 514515 .iter()
Borrow collection entries for iteration without moving or copying the whole collection.
Link to line 515516 .map(|w| format!("{w:08x}"))
Transform each iterator entry, or the successful value of an Option/Result, using the supplied closure.
Link to line 516517 .collect::<Vec<_>>()
Collect the iterator into an owned Vec. This may allocate and belongs to setup, offline fixtures or the main-thread UI path.
Link to line 517518 .join(" ");
Call the displayed operation with these arguments as the next step in “Inspect exact MIDI 2.0 fields”. The chapter describes its role and validation.
Link to line 518519 if self.packets.len() == 16 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Inspect exact MIDI 2.0 fields”.
Link to line 519520 self.packets.remove(0);
Call the displayed operation with these arguments as the next step in “Inspect exact MIDI 2.0 fields”. The chapter describes its role and validation.
Link to line 520521 }
Close the surrounding scope, value or argument list in “Inspect exact MIDI 2.0 fields”.
Link to line 521522 self.packets.push(format!(
Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.
Link to line 522523 "{words}\nGroup {group} · Channel {channel} · {:?}",
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 523524 decoded.kind()
Call the displayed operation with these arguments as the next step in “Inspect exact MIDI 2.0 fields”. The chapter describes its role and validation.
Link to line 524525 ));
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 525526 self.status = "MIDI 2.0 fields preserved · packet inspector".into();
Assign the computed value to self.status. The right-hand expression supplies the new value for this step.
Link to line 526527 }
Close the surrounding scope, value or argument list in “Inspect exact MIDI 2.0 fields”.
Link to line 527Handle explicit device and mode actions
Start, stop, panic and refresh are explicit actions. Mode changes accept only the four example modes, stop the old owner and refresh settings. Unknown types or actions return errors for the status display.
528 "action" => match message["action"].as_str() {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 528529 Some("start") => self.start(message)?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 529530 Some("stop") => self.stop(),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 530531 Some("panic") => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 531532 self.shared
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Handle explicit device and mode actions” explanation above.
Link to line 532533 .panic
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Handle explicit device and mode actions” explanation above.
Link to line 533534 .store(true, std::sync::atomic::Ordering::Release);
Publish the new atomic flag/value using the specified memory ordering.
Link to line 534535 self.status = "All notes off".into();
Assign the computed value to self.status. The right-hand expression supplies the new value for this step.
Link to line 535536 }
Close the surrounding scope, value or argument list in “Handle explicit device and mode actions”.
Link to line 536537 Some("refresh") => self.refresh()?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 537538 Some("mode") => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 538539 let mode = message["mode"]
Bind mode to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 539540 .as_str()
Require a JSON string and borrow its text; incompatible JSON produces None.
Link to line 540541 .filter(|m| ["synth", "effect", "mpe", "midi2"].contains(m))
Keep only entries for which this predicate returns true.
Link to line 541542 .ok_or("Unknown example")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 542543 self.stop();
Call the displayed operation with these arguments as the next step in “Handle explicit device and mode actions”. The chapter describes its role and validation.
Link to line 543544 self.mode = mode.to_owned();
Assign the computed value to self.mode. The right-hand expression supplies the new value for this step.
Link to line 544545 self.refresh()?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 545546 }
Close the surrounding scope, value or argument list in “Handle explicit device and mode actions”.
Link to line 546547 _ => return Err("Unknown action".into()),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 547548 },
Close the surrounding scope, value or argument list in “Handle explicit device and mode actions”.
Link to line 548549 _ => return Err("Unknown message".into()),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 549550 }
Close the surrounding scope, value or argument list in “Handle explicit device and mode actions”.
Link to line 550551 Ok(())
Report successful completion without returning a payload.
Link to line 551552 }
Close the surrounding scope, value or argument list in “Handle explicit device and mode actions”.
Link to line 552Render a hardware-free UI probe
Only Running::Test renders this fixed sample buffer. It exercises prepared audio and telemetry for hidden UI checks without opening an actual native device.
553 fn render_test(&mut self) {
Define render_test. Only Running::Test renders this fixed sample buffer. It exercises prepared audio and telemetry for hidden UI checks without opening an actual native device.
Link to line 553554 if let Some(Running::Test(renderer)) = &mut self.running {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Render a hardware-free UI probe”.
Link to line 554555 let mut samples = [0.; 768];
Bind mutable samples to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 555556 renderer.render(&mut samples);
Call the displayed operation with these arguments as the next step in “Render a hardware-free UI probe”. The chapter describes its role and validation.
Link to line 556557 }
Close the surrounding scope, value or argument list in “Render a hardware-free UI probe”.
Link to line 557558 }
Close the surrounding scope, value or argument list in “Render a hardware-free UI probe”.
Link to line 558Convert coherent words into presentation JSON
Read a newer mailbox record when available, otherwise retain the previous words. Decode meter float bits, packed channel/key/phase and eight-slot voice expression. Combine this with controls, settings, inspector packets and a reconstructed 64-bit frame counter for the page.
559 fn snapshot(&mut self) -> Value {
Define snapshot. Read a newer mailbox record when available, otherwise retain the previous words. Decode meter float bits, packed channel/key/phase and eight-slot voice expression. Combine this with controls, settings, inspector packets and a reconstructed 64-bit frame counter for the page.
Link to line 559560 if let Some(snapshot) = self.shared.telemetry.try_read() {
Attempt to read a complete coherent word snapshot. If none is available, the UI retains its previous record.
Link to line 560561 self.words = snapshot.words;
Assign the computed value to self.words. The right-hand expression supplies the new value for this step.
Link to line 561562 }
Close the surrounding scope, value or argument list in “Convert coherent words into presentation JSON”.
Link to line 562563 if self.running.as_ref().is_some_and(|r| r.errors()) {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Convert coherent words into presentation JSON”.
Link to line 563564 self.status = "Audio backend/processor fault · stop and choose the device again".into();
Assign the computed value to self.status. The right-hand expression supplies the new value for this step.
Link to line 564565 }
Close the surrounding scope, value or argument list in “Convert coherent words into presentation JSON”.
Link to line 565566 let word = |index: usize| f32::from_bits(self.words[index]);
Reconstruct a displayed float from the exact word representation published by the audio owner.
Link to line 566567 let meters = (0..4)
Bind meters to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 567568 .map(|i| json!({"peak":word(2+i*2),"rms":word(3+i*2),"nonfinite":false}))
Transform each iterator entry, or the successful value of an Option/Result, using the supplied closure.
Link to line 568569 .collect::<Vec<_>>();
Collect the iterator into an owned Vec. This may allocate and belongs to setup, offline fixtures or the main-thread UI path.
Link to line 569570 let voices=(0..8).filter_map(|i|{let s=12+i*8;let id=self.words[s];let phase=(id>>16)&255;
Bind voices to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 570571 (phase!=0).then(||json!({"channel":id&255,"key":(id>>8)&255,"phase":(["Idle","Held","Sustained","Released"][phase as usize]),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Convert coherent words into presentation JSON” explanation above.
Link to line 571572 "velocity":word(s+1),"bend":word(s+2)+word(s+3),"pressure":word(s+4),"timbre":word(s+5),"envelope":word(s+6)}))}).collect::<Vec<_>>();
Collect the iterator into an owned Vec. This may allocate and belongs to setup, offline fixtures or the main-thread UI path.
Link to line 572573 json!({"mode":self.mode,"values":self.values,"delay":self.delay,"demo":self.demo,"running":self.running.is_some(),"status":self.status,
Build the main-thread presentation JSON from these named values; the audio owner publishes fixed words instead of serializing JSON.
Link to line 573574 "io":{"outputs":self.outputs,"inputs":self.inputs,"midis":self.midis,"audio":self.mode!="midi2","midi":self.mode=="synth"||self.mode=="mpe","input":self.mode!="midi2","note":if self.mode=="effect" {"Stop audio to change settings. Selected input pairs are mixed to stereo."} else {"Stop audio to change settings. Audio input is optional; notes come from MIDI or the keyboard."}},"meters":meters,"voices":voices,"packets":self.packets,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Convert coherent words into presentation JSON” explanation above.
Link to line 574575 "frames":u64::from(self.words[0])|(u64::from(self.words[1])<<32),"midiDrops":self.words[10],"ranges":RANGES})
Call the displayed operation with these arguments as the next step in “Convert coherent words into presentation JSON”. The chapter describes its role and validation.
Link to line 575576 }
Close the surrounding scope, value or argument list in “Convert coherent words into presentation JSON”.
Link to line 576577}
Close the surrounding scope, value or argument list in “Convert coherent words into presentation JSON”.
Link to line 577Clean up and implement the native bridge
Dropping State stops the session. Bridge owns Rc<RefCell<State>> and implements Callbacks. Reject messages over 4,096 bytes before JSON parsing, dispatch valid messages and turn errors into status text. Snapshot serialization remains on the main thread.
578impl Drop for State {
Declare the state/type or implementation used by this chapter. Dropping State stops the session. Bridge owns Rc<RefCell<State>> and implements Callbacks. Reject messages over 4,096 bytes before JSON parsing, dispatch valid messages and turn errors into status text. Snapshot serialization remains on the main thread.
Link to line 578579 fn drop(&mut self) {
Define drop. Dropping State stops the session. Bridge owns Rc<RefCell<State>> and implements Callbacks. Reject messages over 4,096 bytes before JSON parsing, dispatch valid messages and turn errors into status text. Snapshot serialization remains on the main thread.
Link to line 579580 self.stop();
Call the displayed operation with these arguments as the next step in “Clean up and implement the native bridge”. The chapter describes its role and validation.
Link to line 580581 }
Close the surrounding scope, value or argument list in “Clean up and implement the native bridge”.
Link to line 581582}
Close the surrounding scope, value or argument list in “Clean up and implement the native bridge”.
Link to line 582583struct Bridge(Rc<RefCell<State>>);
Declare the state/type or implementation used by this chapter. Dropping State stops the session. Bridge owns Rc<RefCell<State>> and implements Callbacks. Reject messages over 4,096 bytes before JSON parsing, dispatch valid messages and turn errors into status text. Snapshot serialization remains on the main thread.
Link to line 583584impl Callbacks for Bridge {
Declare the state/type or implementation used by this chapter. Dropping State stops the session. Bridge owns Rc<RefCell<State>> and implements Callbacks. Reject messages over 4,096 bytes before JSON parsing, dispatch valid messages and turn errors into status text. Snapshot serialization remains on the main thread.
Link to line 584585 fn message(&mut self, text: &str) {
Define message. Dropping State stops the session. Bridge owns Rc<RefCell<State>> and implements Callbacks. Reject messages over 4,096 bytes before JSON parsing, dispatch valid messages and turn errors into status text. Snapshot serialization remains on the main thread.
Link to line 585586 let mut state = self.0.borrow_mut();
Bind mutable state to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 586587 let result = (|| -> Result<()> {
Bind result to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 587588 if text.len() > 4096 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Clean up and implement the native bridge”.
Link to line 588589 return Err("Message too large".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 589590 }
Close the surrounding scope, value or argument list in “Clean up and implement the native bridge”.
Link to line 590591 let message: Value = serde_json::from_str(text)?;
Bind message to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 591592 state.handle(&message)
Call the displayed operation with these arguments as the next step in “Clean up and implement the native bridge”. The chapter describes its role and validation.
Link to line 592593 })();
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Clean up and implement the native bridge” explanation above.
Link to line 593594 if let Err(e) = result {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Clean up and implement the native bridge”.
Link to line 594595 state.status = e.to_string();
Assign the computed value to state.status. The right-hand expression supplies the new value for this step.
Link to line 595596 }
Close the surrounding scope, value or argument list in “Clean up and implement the native bridge”.
Link to line 596597 }
Close the surrounding scope, value or argument list in “Clean up and implement the native bridge”.
Link to line 597598 fn snapshot(&mut self) -> Option<String> {
Define snapshot. Dropping State stops the session. Bridge owns Rc<RefCell<State>> and implements Callbacks. Reject messages over 4,096 bytes before JSON parsing, dispatch valid messages and turn errors into status text. Snapshot serialization remains on the main thread.
Link to line 598599 Some(self.0.borrow_mut().snapshot().to_string())
Call the displayed operation with these arguments as the next step in “Clean up and implement the native bridge”. The chapter describes its role and validation.
Link to line 599600 }
Close the surrounding scope, value or argument list in “Clean up and implement the native bridge”.
Link to line 600601}
Close the surrounding scope, value or argument list in “Clean up and implement the native bridge”.
Link to line 601602
Blank line separating the surrounding statements.
Link to line 602Open the window with the default I/O settings
Accept only the four modes and either no UI arguments or --ui-test plus a directory. Create a StandaloneWindow with aspect-ratio locking and default settings enabled. Inject shared controls into the HTML placeholder, embed the bridge, show the editor and pump the native loop. Stop and tear down on exit.
603/// Open the native example window. Devices start only from the page's Start action.
Source note: Open the native example window. Devices start only from the page's Start action.
Link to line 603604/// `--ui-test directory` runs a hidden, hardware-free WebKit/audio fixture instead.
Source note: `--ui-test directory` runs a hidden, hardware-free WebKit/audio fixture instead.
Link to line 604605pub fn run(mode: &str) -> Result<()> {
Define run. Accept only the four modes and either no UI arguments or --ui-test plus a directory. Create a StandaloneWindow with aspect-ratio locking and default settings enabled. Inject shared controls into the HTML placeholder, embed the bridge, show the editor and pump the native loop. Stop and tear down on exit.
Link to line 605606 if !["synth", "effect", "mpe", "midi2"].contains(&mode) {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Open the window with the default I/O settings”.
Link to line 606607 return Err("Unknown example".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 607608 }
Close the surrounding scope, value or argument list in “Open the window with the default I/O settings”.
Link to line 608609 let args: Vec<_> = std::env::args_os().skip(1).collect();
Bind args to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 609610 if args.first().is_some_and(|a| a == "--ui-test") {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Open the window with the default I/O settings”.
Link to line 610611 if args.len() != 2 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Open the window with the default I/O settings”.
Link to line 611612 return Err("usage: --ui-test <screenshot-directory>".into());
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 612613 }
Close the surrounding scope, value or argument list in “Open the window with the default I/O settings”.
Link to line 613614 return probe(std::path::Path::new(&args[1]));
Return this result to the caller; the remaining statements in the function are skipped.
Link to line 614615 }
Close the surrounding scope, value or argument list in “Open the window with the default I/O settings”.
Link to line 615616 if !args.is_empty() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Open the window with the default I/O settings”.
Link to line 616617 return Err(
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 617618 "usage: no arguments for live UI; --render [file.wav] or --offline for fixtures".into(),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Open the window with the default I/O settings” explanation above.
Link to line 618619 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 619620 }
Close the surrounding scope, value or argument list in “Open the window with the default I/O settings”.
Link to line 620621 let state = Rc::new(RefCell::new(State::new(mode, false)));
Bind state to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 621622 let window = StandaloneWindow::new(StandaloneOptions {
Bind window to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 622623 title: "RAVET · Live examples".into(),
Define or initialize title with the displayed type/value. Its ownership and use are described in “Open the window with the default I/O settings”.
Link to line 623624 lock_aspect_ratio: true,
Define or initialize lock_aspect_ratio with the displayed type/value. Its ownership and use are described in “Open the window with the default I/O settings”.
Link to line 624625 ..StandaloneOptions::default()
Call the displayed operation with these arguments as the next step in “Open the window with the default I/O settings”. The chapter describes its role and validation.
Link to line 625626 })?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 626627 let html = ravet_surface::embed_web_controls(include_str!("../../editor/index.html"))
Bind html to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 627628 .ok_or("Missing example control placeholders")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 628629 let editor = window.embed(&html, Bridge(state.clone()))?;
Bind editor to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 629630 editor.set_visible(true);
Call the displayed operation with these arguments as the next step in “Open the window with the default I/O settings”. The chapter describes its role and validation.
Link to line 630631 while window.pump(0.01) {}
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Open the window with the default I/O settings”.
Link to line 631632 state.borrow_mut().stop();
Call the displayed operation with these arguments as the next step in “Open the window with the default I/O settings”. The chapter describes its role and validation.
Link to line 632633 drop(editor);
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 633634 drop(window);
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 634635 Ok(())
Report successful completion without returning a payload.
Link to line 635636}
Close the surrounding scope, value or argument list in “Open the window with the default I/O settings”.
Link to line 636637
Blank line separating the surrounding statements.
Link to line 637Exercise all modes without device I/O
Create a screenshot directory and hidden windows using test State. Drive mode tabs, synth/effect controls, fake channel/rate/buffer choices, voice release and packet inspection. Capture screenshots after the corresponding checks. These probes validate the UI contract, not a physical audio deadline.
638fn probe(directory: &std::path::Path) -> Result<()> {
Define probe. Create a screenshot directory and hidden windows using test State. Drive mode tabs, synth/effect controls, fake channel/rate/buffer choices, voice release and packet inspection. Capture screenshots after the corresponding checks. These probes validate the UI contract, not a physical audio deadline.
Link to line 638639 std::fs::create_dir_all(directory)?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 639640 {
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 640641 let state = Rc::new(RefCell::new(State::new("synth", true)));
Bind state to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 641642 let window = StandaloneWindow::new(StandaloneOptions {
Bind window to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 642643 hidden: true,
Define or initialize hidden with the displayed type/value. Its ownership and use are described in “Exercise all modes without device I/O”.
Link to line 643644 io_settings: false,
Define or initialize io_settings with the displayed type/value. Its ownership and use are described in “Exercise all modes without device I/O”.
Link to line 644645 ..StandaloneOptions::default()
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 645646 })?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 646647 let editor = window.embed(
Bind editor to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 647648 "<body><script>window.ready=true</script></body>",
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 648649 Bridge(state),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 649650 )?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 650651 for _ in 0..20 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 651652 window.pump(0.02);
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 652653 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 653654 assert!(!window.open_settings());
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 654655 assert!(window.eval("window.ready===true&&!document.getElementById('io-settings')")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 655656 drop(editor);
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 656657 drop(window);
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 657658 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 658659
Blank line separating the surrounding statements.
Link to line 659660 for mode in ["synth", "effect", "mpe", "midi2"] {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 660661 let state = Rc::new(RefCell::new(State::new(mode, true)));
Bind state to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 661662 let window = StandaloneWindow::new(StandaloneOptions {
Bind window to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 662663 hidden: true,
Define or initialize hidden with the displayed type/value. Its ownership and use are described in “Exercise all modes without device I/O”.
Link to line 663664 title: format!("RAVET · UI fixture · {mode}"),
Define or initialize title with the displayed type/value. Its ownership and use are described in “Exercise all modes without device I/O”.
Link to line 664665 lock_aspect_ratio: true,
Define or initialize lock_aspect_ratio with the displayed type/value. Its ownership and use are described in “Exercise all modes without device I/O”.
Link to line 665666 ..StandaloneOptions::default()
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 666667 })?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 667668 let html = ravet_surface::embed_web_controls(include_str!("../../editor/index.html"))
Bind html to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 668669 .ok_or("Missing example control placeholders")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 669670 let editor = window.embed(&html, Bridge(state.clone()))?;
Bind editor to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 670671 editor.set_visible(true);
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 671672 let wait = |script: &str| -> Result<()> {
Bind wait to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 672673 for _ in 0..80 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 673674 if window.eval(script)? {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 674675 return Ok(());
Return this result to the caller; the remaining statements in the function are skipped.
Link to line 675676 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 676677 window.pump(0.05);
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 677678 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 678679 Err(format!("UI assertion timed out: {script}").into())
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 679680 };
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 680681 wait("window.ravetExampleReady===true")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 681682 assert!(window.open_settings());
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 682683 wait("document.getElementById('io-settings').open")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 683684 if mode != "midi2" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 684685 assert!(window.eval("document.getElementById('audio-output').value='test-output';document.getElementById('audio-output').dispatchEvent(new Event('change'));true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 685686 wait(
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 686687 "document.getElementById('sample-rate').value==='48000'&&document.querySelectorAll('#output-channels input').length===3",
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 687688 )?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 688689 assert!(window.eval("document.getElementById('buffer-size').value='128';document.getElementById('buffer-size').selectedOptions[0].textContent.includes('2.7 ms')")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 689690 if mode != "effect" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 690691 assert!(window.eval("document.querySelectorAll('#midi-inputs input').length===2&&document.querySelectorAll('#midi-inputs input:checked').length===0")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 691692 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 692693 assert!(window.eval("document.getElementById('audio-input').value='test-input';document.getElementById('audio-input').dispatchEvent(new Event('change'));document.querySelectorAll('#input-channels input').length===2")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 693694 assert!(window.snapshot(&directory.join(format!("{mode}-settings.png")))?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 694695 assert!(window.eval("document.getElementById('audio-input').value='';document.getElementById('audio-input').dispatchEvent(new Event('change'));true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 695696 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 696697 assert!(window.eval("document.getElementById('close-settings').click();true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 697698 if mode == "synth" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 698699 assert!(window.eval("Array.from(document.querySelectorAll('#keyboard .ravet-piano-key')).every(key=>key.disabled&&getComputedStyle(key).opacity==='1')")?, "stopped piano keys must remain opaque");
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 699700 assert!(window.snapshot(&directory.join("synth-stopped.png"))?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 700701 knob_fixture(&window)?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 701702 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 702703
Blank line separating the surrounding statements.
Link to line 703704 if mode == "midi2" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 704705 assert!(window.eval("document.getElementById('encode').click();true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 705706 wait("document.getElementById('packets').textContent.includes('41923c00 abcd0000')")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 706707 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 707708 assert!(window.eval(
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 708709 "window.ravetOpenSettings();document.getElementById('start').click();true"
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 709710 )?);
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 710711 for _ in 0..20 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 711712 state.borrow_mut().render_test();
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 712713 window.pump(0.02);
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 713714 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 714715 assert!(
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 715716 state.borrow().running.is_some(),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 716717 "{}",
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 717718 state.borrow().status
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 718719 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 719720 wait("!document.getElementById('io-settings').open")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 720721 if mode == "synth" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 721722 piano_fixture(&window)?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 722723 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 723724
Blank line separating the surrounding statements.
Link to line 724725 if mode == "effect" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 725726 assert!(window.eval("window.ravetPost({type:'edit',id:1,value:250});window.ravetPost({type:'edit',id:2,value:0.5});window.ravetPost({type:'edit',id:3,value:0.6});window.ravetPost({type:'edit',id:5,value:1});true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 726727 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 727728 assert!(window.eval("window.ravetPost({type:'edit',id:1,value:2});document.querySelector('[data-note=\"60\"]').dispatchEvent(new PointerEvent('pointerdown',{pointerId:1,bubbles:true}));true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 728729 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 729730 for _ in 0..if mode == "effect" { 100 } else { 30 } {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 730731 state.borrow_mut().render_test();
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 731732 window.pump(0.02);
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 732733 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 733734 assert!(state.borrow().words[0] > 0);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 734735 assert!(f32::from_bits(state.borrow().words[6]) > 0.0001);
Reconstruct a displayed float from the exact word representation published by the audio owner.
Link to line 735736 assert!(window.snapshot(&directory.join(format!("{mode}-playing.png")))?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 736737 if mode == "effect" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 737738 assert_eq!(state.borrow().delay, [250., 0.5, 0.6, 0., 1.]);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 738739 wait(
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 739740 "document.getElementById('title').textContent==='Stereo delay'&&document.querySelectorAll('#delay-controls [role=slider]').length===3&&document.getElementById('delay-number-1').value==='250'&&document.getElementById('ping-pong').checked",
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 740741 )?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 741742 assert!(window.eval("document.getElementById('bypass').click();true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 742743 wait("document.getElementById('bypass').checked")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 743744 assert_eq!(state.borrow().delay[3], 1.);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 744745 assert!(window.eval("document.getElementById('main-stop').click();true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 745746 wait(
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 746747 "document.getElementById('main-stop').textContent==='Start audio'&&!document.getElementById('main-stop').disabled",
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 747748 )?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 748749 assert!(state.borrow().running.is_none());
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 749750 assert!(window.eval("document.getElementById('main-stop').click();true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 750751 wait("document.getElementById('main-stop').textContent==='Stop audio'")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 751752 assert!(state.borrow().running.is_some());
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 752753 assert!(window.eval("document.getElementById('demo-loop').click();true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 753754 wait("!document.getElementById('demo-loop').checked")?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 754755 assert!(!state.borrow().demo);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 755756 assert!(window.eval("Array.from(document.getElementById('audio-input').options).every(option=>!option.textContent.includes('Demo')&&option.value!=='demo')")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 756757 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 757758 if mode != "effect" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 758759 assert_eq!(state.borrow().values[0], 2.);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 759760 assert!(window.eval("document.querySelector('[data-note=\"60\"]').dispatchEvent(new PointerEvent('pointerup',{pointerId:1,bubbles:true}));true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 760761 for _ in 0..150 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Exercise all modes without device I/O”.
Link to line 761762 state.borrow_mut().render_test();
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 762763 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 763764 assert!(
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 764765 state.borrow_mut().snapshot()["voices"]
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Exercise all modes without device I/O” explanation above.
Link to line 765766 .as_array()
Require a JSON array and borrow its entries; incompatible JSON produces None.
Link to line 766767 .expect("voices")
Require the invariant “voices”. expect panics if it is broken; external inputs must be validated before relying on it.
Link to line 767768 .is_empty()
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 768769 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 769770 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 770771 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 771772 window.pump(0.1);
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 772773 layout_fixture(&window, mode, directory)?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 773774 assert!(window.snapshot(&directory.join(format!("{mode}.png")))?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 774775 state.borrow_mut().stop();
Call the displayed operation with these arguments as the next step in “Exercise all modes without device I/O”. The chapter describes its role and validation.
Link to line 775776 drop(editor);
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 776777 drop(window);
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 777778 println!("PASS {mode} native UI/control/audio fixture (no device opened)");
Report this explicit fixture result to stdout; printing belongs to the offline/control path, not the audio callback.
Link to line 778779 }
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 779780 settings_fixture()?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 780781 Ok(())
Report successful completion without returning a payload.
Link to line 781782}
Close the surrounding scope, value or argument list in “Exercise all modes without device I/O”.
Link to line 782783
Blank line separating the surrounding statements.
Link to line 783Check uniform design-canvas scaling
Request several viewport sizes, query the page’s actual layout and verify the 900×780 content scales uniformly. Wide/short and narrow/tall requests are constrained by the locked aspect ratio. Validate dimensions and unclipped controls rather than relying on a screenshot alone.
784fn layout_fixture(
Define layout_fixture. Request several viewport sizes, query the page’s actual layout and verify the 900×780 content scales uniformly. Wide/short and narrow/tall requests are constrained by the locked aspect ratio. Validate dimensions and unclipped controls rather than relying on a screenshot alone.
Link to line 784785 window: &StandaloneWindow,
Define or initialize window with the displayed type/value. Its ownership and use are described in “Check uniform design-canvas scaling”.
Link to line 785786 mode: &str,
Define or initialize mode with the displayed type/value. Its ownership and use are described in “Check uniform design-canvas scaling”.
Link to line 786787 directory: &std::path::Path,
Define or initialize directory with the displayed type/value. Its ownership and use are described in “Check uniform design-canvas scaling”.
Link to line 787788) -> Result<()> {
Complete the function’s parameter list and specify the return type. A Result preserves the explicit success/error distinction.
Link to line 788789 assert!(window.eval("window.ravetLayoutBaseline=Array.from(document.querySelectorAll('header,h1,.tabs,.dial,.panel,input[type=number],footer')).filter(node=>{const rect=node.getBoundingClientRect();return rect.width>0&&rect.height>0}).map(node=>({node,rect:node.getBoundingClientRect()}));window.ravetExampleScale===1")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 789790 for (width, height, actual_width, actual_height, scale, label) in [
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Check uniform design-canvas scaling”.
Link to line 790791 (720., 624., 720, 624, 0.8, "minimum"),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check uniform design-canvas scaling” explanation above.
Link to line 791792 (1080., 936., 1080, 936, 1.2, "large"),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check uniform design-canvas scaling” explanation above.
Link to line 792793 (1200., 624., 720, 624, 0.8, "wide-short"),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check uniform design-canvas scaling” explanation above.
Link to line 793794 (720., 1000., 720, 624, 0.8, "narrow-tall"),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check uniform design-canvas scaling” explanation above.
Link to line 794795 (900., 780., 900, 780, 1., "default"),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check uniform design-canvas scaling” explanation above.
Link to line 795796 ] {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check uniform design-canvas scaling” explanation above.
Link to line 796797 assert!(window.set_size(width, height));
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 797798 let check = format!(
Bind check to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 798799 "window.innerWidth==={actual_width}&&window.innerHeight==={actual_height}&&Math.abs(window.ravetExampleScale-{scale})<0.001"
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check uniform design-canvas scaling” explanation above.
Link to line 799800 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 800801 let mut ready = false;
Bind mutable ready to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 801802 for _ in 0..80 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Check uniform design-canvas scaling”.
Link to line 802803 if window.eval(&check)? {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Check uniform design-canvas scaling”.
Link to line 803804 ready = true;
Assign the computed value to ready. The right-hand expression supplies the new value for this step.
Link to line 804805 break;
End the nearest loop when its bounded work or input condition is complete.
Link to line 805806 }
Close the surrounding scope, value or argument list in “Check uniform design-canvas scaling”.
Link to line 806807 window.pump(0.05);
Call the displayed operation with these arguments as the next step in “Check uniform design-canvas scaling”. The chapter describes its role and validation.
Link to line 807808 }
Close the surrounding scope, value or argument list in “Check uniform design-canvas scaling”.
Link to line 808809 assert!(ready, "{mode} {label} native aspect/viewport mismatch");
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 809810 assert!(window.eval(&format!("window.ravetLayoutBaseline.every(item=>{{const rect=item.node.getBoundingClientRect();return Math.abs(rect.width-item.rect.width*{scale})<1&&Math.abs(rect.height-item.rect.height*{scale})<1&&Math.abs(rect.top-item.rect.top*{scale})<1&&Math.abs(rect.left-item.rect.left*{scale})<1}})"))?,"{mode} {label} must scale all UI dimensions and positions uniformly");
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 810811 assert!(window.eval("window.ravetLayoutBaseline.every(item=>{const rect=item.node.getBoundingClientRect();return rect.left>=-1&&rect.top>=-1&&rect.right<=window.innerWidth+1&&rect.bottom<=window.innerHeight+1})&&document.documentElement.scrollHeight<=window.innerHeight+1&&document.documentElement.scrollWidth<=window.innerWidth+1")?,"{mode} {label} content clipped/overflows");
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 811812 if mode != "midi2" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Check uniform design-canvas scaling”.
Link to line 812813 assert!(window.eval("Array.from(document.querySelectorAll('#meters-panel .reading')).every(reading=>reading.getBoundingClientRect().bottom<=document.getElementById('meters-panel').getBoundingClientRect().bottom-1)")?,"{mode} {label} meter readings overflow");
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 813814 }
Close the surrounding scope, value or argument list in “Check uniform design-canvas scaling”.
Link to line 814815 if label == "minimum" || label == "large" {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Check uniform design-canvas scaling”.
Link to line 815816 assert!(window.snapshot(&directory.join(format!("{mode}-{label}.png")))?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 816817 }
Close the surrounding scope, value or argument list in “Check uniform design-canvas scaling”.
Link to line 817818 }
Close the surrounding scope, value or argument list in “Check uniform design-canvas scaling”.
Link to line 818819 Ok(())
Report successful completion without returning a payload.
Link to line 819820}
Close the surrounding scope, value or argument list in “Check uniform design-canvas scaling”.
Link to line 820821
Blank line separating the surrounding statements.
Link to line 821Verify settings opt-out and default behavior
Open three successive hidden windows with an in-memory native preferences fixture. Save device IDs, channel pairs, a 96 kHz rate, a 256-frame buffer and one MIDI input; confirm the next window restores these selections without starting audio. Then save unavailable IDs and confirm the next window clears them.
822fn settings_fixture() -> Result<()> {
Define settings_fixture. Open three successive hidden windows with an in-memory native preferences fixture. Save device IDs, channel pairs, a 96 kHz rate, a 256-frame buffer and one MIDI input; confirm the next window restores these selections without starting audio. Then save unavailable IDs and confirm the next window clears them.
Link to line 822823 for pass in 0..3 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Verify settings opt-out and default behavior”.
Link to line 823824 let state = Rc::new(RefCell::new(State::new("synth", true)));
Bind state to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 824825 let window = StandaloneWindow::new(StandaloneOptions {
Bind window to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 825826 hidden: true,
Define or initialize hidden with the displayed type/value. Its ownership and use are described in “Verify settings opt-out and default behavior”.
Link to line 826827 title: "RAVET · settings restore fixture".into(),
Define or initialize title with the displayed type/value. Its ownership and use are described in “Verify settings opt-out and default behavior”.
Link to line 827828 ..Default::default()
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 828829 })?;
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 829830 let html =
Bind html to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 830831 ravet_surface::embed_web_controls(include_str!("../../editor/index.html")).unwrap();
Define or initialize ravet_surface with the displayed type/value. Its ownership and use are described in “Verify settings opt-out and default behavior”.
Link to line 831832 let editor = window.embed(&html, Bridge(state.clone()))?;
Bind editor to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 832833 editor.set_visible(true);
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 833834 for _ in 0..80 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Verify settings opt-out and default behavior”.
Link to line 834835 if window.eval("window.ravetExampleReady===true")? {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Verify settings opt-out and default behavior”.
Link to line 835836 break;
End the nearest loop when its bounded work or input condition is complete.
Link to line 836837 }
Close the surrounding scope, value or argument list in “Verify settings opt-out and default behavior”.
Link to line 837838 window.pump(0.05);
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 838839 }
Close the surrounding scope, value or argument list in “Verify settings opt-out and default behavior”.
Link to line 839840 assert!(window.eval("window.ravetExampleReady===true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 840841 if pass == 0 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Verify settings opt-out and default behavior”.
Link to line 841842 assert!(window.eval(r#"(()=>{
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 842843 const get=id=>document.getElementById(id),change=node=>node.dispatchEvent(new Event('change',{bubbles:true}));
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 843844 get('audio-output').value='test-output';change(get('audio-output'));
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 844845 get('audio-input').value='test-input';change(get('audio-input'));
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 845846 get('sample-rate').value='96000';change(get('sample-rate'));
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 846847 get('buffer-size').value='256';change(get('buffer-size'));
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 847848 for(const [id,value] of [['output-channels','4'],['input-channels','2'],['midi-inputs','midi-b']]){
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Verify settings opt-out and default behavior” explanation above.
Link to line 848849 for(const check of get(id).querySelectorAll('input'))check.checked=check.value===value;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Verify settings opt-out and default behavior” explanation above.
Link to line 849850 change(get(id));
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 850851 }return true;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Verify settings opt-out and default behavior” explanation above.
Link to line 851852 })()"#)?);
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 852853 window.pump(0.1);
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 853854 } else if pass == 1 {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Verify settings opt-out and default behavior” explanation above.
Link to line 854855 assert!(window.eval(r#"document.getElementById('audio-output').value==='test-output'&&document.getElementById('audio-input').value==='test-input'&&document.getElementById('sample-rate').value==='96000'&&document.getElementById('buffer-size').value==='256'&&['output-channels','input-channels','midi-inputs'].every(id=>document.querySelectorAll('#'+id+' input:checked').length===1)&&document.querySelector('#output-channels input:checked').value==='4'&&document.querySelector('#input-channels input:checked').value==='2'&&document.querySelector('#midi-inputs input:checked').value==='midi-b'"#)?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 855856 assert!(state.borrow().running.is_none());
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 856857 assert!(window.eval("window.webkit.messageHandlers.ravetSettings.postMessage({version:1,output:'missing-output',input:'missing-input',sample_rate:96000,buffer_size:256,output_pairs:[0],input_pairs:[0],midis:['missing-midi']});true")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 857858 window.pump(0.1);
Call the displayed operation with these arguments as the next step in “Verify settings opt-out and default behavior”. The chapter describes its role and validation.
Link to line 858859 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Verify settings opt-out and default behavior” explanation above.
Link to line 859860 assert!(window.eval("document.getElementById('audio-output').value===''&&document.getElementById('audio-input').value===''&&document.querySelectorAll('#midi-inputs input:checked').length===0")?);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 860861 }
Close the surrounding scope, value or argument list in “Verify settings opt-out and default behavior”.
Link to line 861862 drop(editor);
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 862863 drop(window);
Release this owner on the control/offline thread after its running activity has been stopped.
Link to line 863864 }
Close the surrounding scope, value or argument list in “Verify settings opt-out and default behavior”.
Link to line 864865 println!(
Report this explicit fixture result to stdout; printing belongs to the offline/control path, not the audio callback.
Link to line 865866 "PASS Audio/MIDI selection restore, unavailable devices and no automatic start (in-memory native preferences fixture)"
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Verify settings opt-out and default behavior” explanation above.
Link to line 866867 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 867868 Ok(())
Report successful completion without returning a payload.
Link to line 868869}
Close the surrounding scope, value or argument list in “Verify settings opt-out and default behavior”.
Link to line 869870
Blank line separating the surrounding statements.
Link to line 870Check keyboard and numeric control gestures
Drive the shared knob through keyboard changes and numeric entry, then inspect its displayed values. These tests exercise the control component’s edit/refresh contract, not a host automation lane.
871fn knob_fixture(window: &StandaloneWindow) -> Result<()> {
Define knob_fixture. Drive the shared knob through keyboard changes and numeric entry, then inspect its displayed values. These tests exercise the control component’s edit/refresh contract, not a host automation lane.
Link to line 871872 assert!(window.eval(r#"(()=>{
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 872873 if(document.querySelectorAll('input[type=range]').length!==0)return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check keyboard and numeric control gestures” explanation above.
Link to line 873874 const dial=document.createElement('div'),number=document.createElement('input');number.type='number';
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 874875 const messages=[],knob=new RavetControls.Knob(dial,number,{id:90,minimum:20,maximum:20000,step:1,value:200,logarithmic:true},m=>{messages.push(m);return true});
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 875876 dial.dispatchEvent(new PointerEvent('pointerdown',{button:0,pointerId:99,clientY:100}));
Call the displayed operation with these arguments as the next step in “Check keyboard and numeric control gestures”. The chapter describes its role and validation.
Link to line 876877 dial.dispatchEvent(new PointerEvent('pointermove',{pointerId:99,clientY:50}));
Call the displayed operation with these arguments as the next step in “Check keyboard and numeric control gestures”. The chapter describes its role and validation.
Link to line 877878 if(knob.update(400)||Math.abs(knob.current-2000)>1)return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check keyboard and numeric control gestures” explanation above.
Link to line 878879 dial.dispatchEvent(new PointerEvent('pointercancel',{pointerId:99}));
Call the displayed operation with these arguments as the next step in “Check keyboard and numeric control gestures”. The chapter describes its role and validation.
Link to line 879880 if(messages.map(m=>m.type).join(',')!=='begin,value,end')return false;
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 880881 knob.update(200);dial.dispatchEvent(new KeyboardEvent('keydown',{key:'End'}));dial.dispatchEvent(new KeyboardEvent('keyup',{key:'End'}));
Call the displayed operation with these arguments as the next step in “Check keyboard and numeric control gestures”. The chapter describes its role and validation.
Link to line 881882 if(knob.current!==20000)return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check keyboard and numeric control gestures” explanation above.
Link to line 882883 number.value='-1';number.dispatchEvent(new Event('change'));if(knob.current!==20)return false;
Assign the computed value to number.value. The right-hand expression supplies the new value for this step.
Link to line 883884 if(!knob.dispose())return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check keyboard and numeric control gestures” explanation above.
Link to line 884885 let rejected=true;const retry=new RavetControls.Knob(dial,null,{id:91,minimum:0,maximum:1,value:.6},m=>m.type!=='end'||!rejected);
Bind rejected to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 885886 retry.begin();if(retry.dispose()||!retry.active)return false;rejected=false;if(!retry.dispose())return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check keyboard and numeric control gestures” explanation above.
Link to line 886887 const denied=new RavetControls.Knob(dial,null,{id:92,minimum:0,maximum:1},()=>false);if(denied.begin()||denied.active||!denied.dispose())return false;
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 887888 return true;
Return this result to the caller; the remaining statements in the function are skipped.
Link to line 888889 })()"#)?);
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 889890 Ok(())
Report successful completion without returning a payload.
Link to line 890891}
Close the surrounding scope, value or argument list in “Check keyboard and numeric control gestures”.
Link to line 891892
Blank line separating the surrounding statements.
Link to line 892Check pointer-held notes and cancellation
Drive the shared piano widget and inspect held-note state. Verify release on cancellation/focus transitions so a lost UI interaction does not leave an on-screen note held.
893fn piano_fixture(window: &StandaloneWindow) -> Result<()> {
Define piano_fixture. Drive the shared piano widget and inspect held-note state. Verify release on cancellation/focus transitions so a lost UI interaction does not leave an on-screen note held.
Link to line 893894 assert!(window.eval(r#"(()=>{
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 894895 const root=document.getElementById('keyboard'),white=root.querySelector('[data-note="60"]'),black=root.querySelector('[data-note="61"]');
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 895896 const w=white.getBoundingClientRect(),b=black.getBoundingClientRect();
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 896897 if(b.height>=w.height*.7||b.width>=w.width||b.left>=w.right||b.left<=w.left||root.querySelectorAll('.white').length!==15||root.querySelectorAll('.black').length!==10)return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check pointer-held notes and cancellation” explanation above.
Link to line 897898 const outer=document.createElement('div');outer.style.cssText='position:fixed;left:10px;top:10px;width:300px;height:100px;z-index:1000';document.body.append(outer);
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 898899 const messages=[],active=new Map();
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 899900 const piano=new RavetControls.PianoKeyboard(outer,{firstNote:60,lastNote:72,onNoteOn:(note,source)=>{active.set(source,note);messages.push(['on',note]);return true},onNoteOff:source=>{messages.push(['off',active.get(source)]);active.delete(source)}});
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 900901 const key=note=>outer.querySelector(`[data-note="${note}"]`),pointer=(node,type,id,x,y)=>node.dispatchEvent(new PointerEvent(type,{button:0,pointerId:id,clientX:x,clientY:y,bubbles:true}));
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 901902 const c=key(60).getBoundingClientRect(),e=key(64).getBoundingClientRect(),d=key(62).getBoundingClientRect();
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 902903 pointer(key(60),'pointerdown',31,c.left+5,c.bottom-5);pointer(key(64),'pointerdown',32,e.left+5,e.bottom-5);
Call the displayed operation with these arguments as the next step in “Check pointer-held notes and cancellation”. The chapter describes its role and validation.
Link to line 903904 if(active.size!==2)return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check pointer-held notes and cancellation” explanation above.
Link to line 904905 pointer(outer,'pointermove',31,d.left+5,d.bottom-5);if(messages.slice(-2).map(m=>m.join(':')).join(',')!=='off:60,on:62')return false;
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 905906 pointer(outer,'pointercancel',31,0,0);if(active.size!==1)return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check pointer-held notes and cancellation” explanation above.
Link to line 906907 piano.releaseAll();if(active.size!==0)return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check pointer-held notes and cancellation” explanation above.
Link to line 907908 piano.setActiveNotes([61]);if(!key(61).classList.contains('held')||messages.length!==6)return false;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check pointer-held notes and cancellation” explanation above.
Link to line 908909 key(60).dispatchEvent(new KeyboardEvent('keydown',{key:' ',bubbles:true}));key(60).dispatchEvent(new KeyboardEvent('keyup',{key:' ',bubbles:true}));
Call the displayed operation with these arguments as the next step in “Check pointer-held notes and cancellation”. The chapter describes its role and validation.
Link to line 909910 if(active.size!==0||messages.slice(-2).map(m=>m.join(':')).join(',')!=='on:60,off:60')return false;
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 910911 piano.dispose();outer.remove();return true;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Check pointer-held notes and cancellation” explanation above.
Link to line 911912 })()"#)?);
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 912913 Ok(())
Report successful completion without returning a payload.
Link to line 913914}
Close the surrounding scope, value or argument list in “Check pointer-held notes and cancellation”.
Link to line 914