From e498421fb832397c1053348f6afca94f3da7208a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 24 Sep 2026 13:09:42 +0000 Subject: [PATCH 1/3] ci: fix clippy 1.98 lints and setup-android's removed tools package Rust 1.98's clippy flags manual slice fills, drain-collect and a sort_by that sort_by_key covers. setup-android@v3 installs the legacy `tools` package by default, which sdkmanager can no longer find. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01F2aJfyqNAu3fSdazYDjPQ3 --- .github/workflows/ci.yml | 4 ++++ crates/hocket-core/src/audio/dsp/biquad.rs | 4 +--- crates/hocket-core/src/audio/dsp/loudness.rs | 4 +--- crates/hocket-core/src/audio/dsp/normalise.rs | 12 +++--------- crates/hocket-core/src/connect/engine.rs | 4 ++-- crates/hocket-core/src/core/queries.rs | 2 +- 6 files changed, 12 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8e55f4..bf075a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,6 +73,10 @@ jobs: distribution: temurin java-version: 21 - uses: android-actions/setup-android@v3 + with: + # The default also asks for the legacy `tools` package, which the + # SDK repository no longer serves. + packages: platform-tools - run: yes | sdkmanager --licenses >/dev/null && sdkmanager "platforms;android-37" "build-tools;36.0.0" "ndk;27.2.12479018" - run: cargo install cargo-ndk typeshare-cli - run: scripts/gen-bindings.sh diff --git a/crates/hocket-core/src/audio/dsp/biquad.rs b/crates/hocket-core/src/audio/dsp/biquad.rs index b81ec3e..aa3da84 100644 --- a/crates/hocket-core/src/audio/dsp/biquad.rs +++ b/crates/hocket-core/src/audio/dsp/biquad.rs @@ -208,9 +208,7 @@ impl Biquad { } pub fn reset(&mut self) { - for s in &mut self.state { - *s = [0.0; 2]; - } + self.state.fill([0.0; 2]); } /// Process one sample of one channel. diff --git a/crates/hocket-core/src/audio/dsp/loudness.rs b/crates/hocket-core/src/audio/dsp/loudness.rs index 4f78495..a78ed31 100644 --- a/crates/hocket-core/src/audio/dsp/loudness.rs +++ b/crates/hocket-core/src/audio/dsp/loudness.rs @@ -164,9 +164,7 @@ impl LoudnessMeter { .map(|(sum, w)| w * sum / n) .sum(); self.sub_blocks.push(power); - for c in &mut self.current { - *c = 0.0; - } + self.current.fill(0.0); self.current_frames = 0; } diff --git a/crates/hocket-core/src/audio/dsp/normalise.rs b/crates/hocket-core/src/audio/dsp/normalise.rs index 547d702..f1a9e06 100644 --- a/crates/hocket-core/src/audio/dsp/normalise.rs +++ b/crates/hocket-core/src/audio/dsp/normalise.rs @@ -111,13 +111,9 @@ impl Normaliser { pub fn reset(&mut self) { self.filter.reset(); - for c in &mut self.current { - *c = 0.0; - } + self.current.fill(0.0); self.current_frames = 0; - for r in &mut self.ring { - *r = 0.0; - } + self.ring.fill(0.0); self.ring_pos = 0; self.ring_filled = 0; self.gain_db = 0.0; @@ -135,9 +131,7 @@ impl Normaliser { self.ring[self.ring_pos] = power; self.ring_pos = (self.ring_pos + 1) % self.ring.len(); self.ring_filled = (self.ring_filled + 1).min(self.ring.len()); - for c in &mut self.current { - *c = 0.0; - } + self.current.fill(0.0); self.current_frames = 0; if let Some(l) = self.short_term_lufs() { if l > GATE_LUFS { diff --git a/crates/hocket-core/src/connect/engine.rs b/crates/hocket-core/src/connect/engine.rs index 8ee9656..582ab80 100644 --- a/crates/hocket-core/src/connect/engine.rs +++ b/crates/hocket-core/src/connect/engine.rs @@ -1101,7 +1101,7 @@ impl Engine { self.lan_blocklist.clear(); self.lan_strikes.clear(); // Inbound members were admitted under the old key. - let inbound: Vec = self.inbound.drain(..).collect(); + let inbound: Vec = std::mem::take(&mut self.inbound); for p in inbound { self.out.push(Output::WireOut { peer: p.clone(), @@ -2681,7 +2681,7 @@ impl Engine { self.last_ping_at = 0.0; self.send_ping(); // Say goodbye to anyone we were serving: they'll re-elect. - let inbound: Vec = self.inbound.drain(..).collect(); + let inbound: Vec = std::mem::take(&mut self.inbound); for p in inbound { self.out.push(Output::WireOut { peer: p.clone(), diff --git a/crates/hocket-core/src/core/queries.rs b/crates/hocket-core/src/core/queries.rs index 3b7e14a..95a513f 100644 --- a/crates/hocket-core/src/core/queries.rs +++ b/crates/hocket-core/src/core/queries.rs @@ -267,7 +267,7 @@ impl Actor { let Some(api) = self.api() else { // Offline: the artist's most played tracks from the mirror. let mut tracks = self.db.artist_tracks(&id).unwrap_or_default(); - tracks.sort_by(|a, b| b.play_count.cmp(&a.play_count)); + tracks.sort_by_key(|t| std::cmp::Reverse(t.play_count)); tracks.truncate(count as usize); let _ = reply.send(QueryResult::TrackList(tracks)); return; From 7d44a6ccb2bbd3a7bdba449afd33f2eea78ac351 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 24 Sep 2026 13:11:07 +0000 Subject: [PATCH 2/3] ci: install the android-37.1 platform the modules compile against sdkmanager has no `platforms;android-37`; SDK 37 platforms carry a minor version, and the modules set compileSdk 37 with compileSdkMinor 1. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01F2aJfyqNAu3fSdazYDjPQ3 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf075a8..a6154b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,7 +77,7 @@ jobs: # The default also asks for the legacy `tools` package, which the # SDK repository no longer serves. packages: platform-tools - - run: yes | sdkmanager --licenses >/dev/null && sdkmanager "platforms;android-37" "build-tools;36.0.0" "ndk;27.2.12479018" + - run: yes | sdkmanager --licenses >/dev/null && sdkmanager "platforms;android-37.1" "build-tools;36.0.0" "ndk;27.2.12479018" - run: cargo install cargo-ndk typeshare-cli - run: scripts/gen-bindings.sh - run: scripts/build-android-core.sh release From 5f1666db45c61ed7e763fab43a33cd4293b96d82 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 24 Sep 2026 13:33:29 +0000 Subject: [PATCH 3/3] test: make the discarded pre-buffer check race-free pre_buffer_is_reused_by_a_matching_load failed on a busy CI runner: the 1 s pre-buffer load can finish before the test even sends the discard, and reporting it then is correct. Only reports after the engine has handled the discard now count, marked by a seek's synchronous Position report. The check still fails if discard stops dropping the late load. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01F2aJfyqNAu3fSdazYDjPQ3 --- crates/hocket-core/src/audio/native/engine.rs | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/crates/hocket-core/src/audio/native/engine.rs b/crates/hocket-core/src/audio/native/engine.rs index 838f3e1..f65d7f1 100644 --- a/crates/hocket-core/src/audio/native/engine.rs +++ b/crates/hocket-core/src/audio/native/engine.rs @@ -1460,14 +1460,35 @@ mod tests { rig.wait_for(Duration::from_secs(5), |r| { matches!(r, BackendReport::Ended { .. }) }); - // Discarded pre-buffers never report. + // Discarded pre-buffers never report. The load may finish before the + // discard is even sent, so only reports after it count: a seek + // reports its position synchronously, right after the engine has + // handled the discard. + rig.backend + .load(rig.wav("a.wav", 48_000, 48_000 * 2), None, 0, false) + .unwrap(); + rig.wait_for(Duration::from_secs(5), |r| { + matches!(r, BackendReport::Paused { .. }) + }); let b = rig.wav("b.wav", 48_000, 48_000); + rig.take(); rig.backend.pre_buffer(b, 0).unwrap(); rig.backend.discard_pre_buffer().unwrap(); + rig.backend.seek(1234).unwrap(); + let is_barrier = |r: &BackendReport| { + matches!( + r, + BackendReport::Position { + position_ms: 1234, + .. + } + ) + }; + rig.wait_for(Duration::from_secs(5), is_barrier); thread::sleep(Duration::from_millis(300)); - assert!(!rig - .reports - .lock() + let reports = rig.reports.lock(); + let barrier = reports.iter().position(is_barrier).unwrap(); + assert!(!reports[barrier..] .iter() .any(|r| matches!(r, BackendReport::PreBufferReady { key } if key == "b.wav"))); }