Skip to content

Commit adf92c8

Browse files
kixelatedclaude
andauthored
moq-boy: lower default volume and add volume slider (#1313)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent a144025 commit adf92c8

5 files changed

Lines changed: 61 additions & 16 deletions

File tree

js/moq-boy/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@moq/boy",
33
"type": "module",
4-
"version": "0.2.5",
4+
"version": "0.2.6",
55
"description": "MoQ Boy - Crowd-controlled Game Boy streaming via MoQ",
66
"license": "(MIT OR Apache-2.0)",
77
"repository": {

js/moq-boy/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export class Game {
7171
readonly active = new Moq.Signals.Signal(false);
7272
readonly latency = new Moq.Signals.Signal<Watch.Latency>("real-time");
7373
readonly userMuted = new Moq.Signals.Signal(false);
74+
readonly volume = new Moq.Signals.Signal(0.25);
7475
readonly status = new Moq.Signals.Signal<GameStatus | undefined>(undefined);
7576
readonly viewerId = new Moq.Signals.Signal<string | undefined>(undefined);
7677

@@ -147,7 +148,7 @@ export class Game {
147148
this.#signals.run(this.#runAudioPaused.bind(this, audioPaused));
148149

149150
this.audioEmitter = new Watch.Audio.Emitter(this.audioDecoder, {
150-
volume: 0.5,
151+
volume: this.volume,
151152
muted: this.userMuted,
152153
paused: audioPaused,
153154
});

js/moq-boy/src/ui/components/Controls.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,25 @@ import { createPair } from "@moq/signals/solid";
22
import { For } from "solid-js";
33
import { useGameUI } from "../hooks/use-boy-ui";
44

5-
/** All game controls: D-pad, A/B, Start/Select, Mute, Reset, Key hints. */
5+
/** All game controls: D-pad, A/B, Start/Select, Mute, Volume, Reset, Key hints. */
66
export default function Controls() {
77
const ctx = useGameUI();
88
const game = ctx.game;
99

1010
const [userMuted, setUserMuted] = createPair(game.userMuted);
11+
const [volume, setVolume] = createPair(game.volume);
1112

1213
const toggleMute = (e: MouseEvent) => {
1314
e.stopPropagation();
1415
setUserMuted((prev) => !prev);
1516
};
1617

18+
const onVolumeInput = (e: InputEvent) => {
19+
e.stopPropagation();
20+
const el = e.currentTarget as HTMLInputElement;
21+
setVolume(Number.parseFloat(el.value) / 100);
22+
};
23+
1724
const onReset = (e: MouseEvent) => {
1825
e.stopPropagation();
1926
game.sendCommand({ type: "reset" });
@@ -25,6 +32,20 @@ export default function Controls() {
2532
<ABButtons />
2633
<MetaButtons />
2734

35+
<div class="boy__volume">
36+
<span class="boy__volume-label">Vol {Math.round(volume() * 100)}</span>
37+
<input
38+
type="range"
39+
class="boy__volume-slider"
40+
aria-label="Volume"
41+
min="0"
42+
max="100"
43+
value={Math.round(volume() * 100)}
44+
onInput={onVolumeInput}
45+
onClick={(e) => e.stopPropagation()}
46+
/>
47+
</div>
48+
2849
<div class="boy__util-buttons">
2950
<button
3051
type="button"

js/moq-boy/src/ui/styles/controls.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,27 @@
168168
border-color: var(--color-red);
169169
}
170170

171+
/* Volume slider */
172+
.boy__volume {
173+
width: 100%;
174+
display: flex;
175+
flex-direction: column;
176+
align-items: center;
177+
gap: 0.3rem;
178+
}
179+
180+
.boy__volume-label {
181+
font-family: monospace;
182+
font-size: 0.65rem;
183+
color: var(--boy-text-muted);
184+
}
185+
186+
.boy__volume-slider {
187+
width: 100%;
188+
accent-color: var(--boy-accent);
189+
cursor: pointer;
190+
}
191+
171192
/* Jitter/buffer slider */
172193
.boy__jitter {
173194
width: 100%;

rs/moq-relay/src/auth.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,7 +2169,7 @@ api = "https://api.example.com/access"
21692169

21702170
// ---------------------------------------------------------------------
21712171
// mTLS test: stand up a real HTTPS server requiring + verifying client
2172-
// certs, and assert that --auth-tls-identity actually presents the cert.
2172+
// certs, and assert that --auth-tls-cert/--auth-tls-key present the cert.
21732173
// ---------------------------------------------------------------------
21742174

21752175
use rcgen::{CertificateParams, KeyPair};
@@ -2180,14 +2180,15 @@ api = "https://api.example.com/access"
21802180
struct MtlsFixture {
21812181
_dir: TempDir,
21822182
ca_pem_path: PathBuf,
2183-
client_identity_path: PathBuf,
2183+
client_cert_path: PathBuf,
2184+
client_key_path: PathBuf,
21842185
base_url: String,
21852186
key: Key,
21862187
}
21872188

21882189
/// Spin up an HTTPS server on 127.0.0.1 that requires a client cert signed
21892190
/// by our test CA and serves `/keys/test-key.jwk`. Returns paths to the CA
2190-
/// PEM and the client identity bundle so callers can configure `Auth`.
2191+
/// PEM and the client cert/key files so callers can configure `Auth`.
21912192
async fn mtls_fixture() -> MtlsFixture {
21922193
// Install a default crypto provider for rustls. Idempotent across tests.
21932194
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
@@ -2215,16 +2216,14 @@ api = "https://api.example.com/access"
22152216
.push(rcgen::DnType::CommonName, "test-client");
22162217
let client_cert = client_params.signed_by(&client_kp, &ca_cert, &ca_kp).unwrap();
22172218

2218-
// 4. Write CA + client identity (cert chain + private key bundle) to temp files.
2219+
// 4. Write CA + client cert/key to temp files.
22192220
let dir = TempDir::new().unwrap();
22202221
let ca_pem_path = dir.path().join("ca.pem");
2221-
let client_identity_path = dir.path().join("client.pem");
2222+
let client_cert_path = dir.path().join("client.cert.pem");
2223+
let client_key_path = dir.path().join("client.key.pem");
22222224
std::fs::write(&ca_pem_path, ca_cert.pem()).unwrap();
2223-
std::fs::write(
2224-
&client_identity_path,
2225-
format!("{}{}", client_cert.pem(), client_kp.serialize_pem()),
2226-
)
2227-
.unwrap();
2225+
std::fs::write(&client_cert_path, client_cert.pem()).unwrap();
2226+
std::fs::write(&client_key_path, client_kp.serialize_pem()).unwrap();
22282227

22292228
// 5. Build a rustls ServerConfig requiring + verifying client certs against the CA.
22302229
let mut roots = rustls::RootCertStore::empty();
@@ -2262,7 +2261,8 @@ api = "https://api.example.com/access"
22622261
MtlsFixture {
22632262
_dir: dir,
22642263
ca_pem_path,
2265-
client_identity_path,
2264+
client_cert_path,
2265+
client_key_path,
22662266
base_url: format!("https://{addr}"),
22672267
key,
22682268
}
@@ -2277,7 +2277,8 @@ api = "https://api.example.com/access"
22772277
key_dir: Some(format!("{}/keys/", fx.base_url)),
22782278
tls: AuthTls {
22792279
root: vec![fx.ca_pem_path.clone()],
2280-
identity: Some(fx.client_identity_path.clone()),
2280+
cert: Some(fx.client_cert_path.clone()),
2281+
key: Some(fx.client_key_path.clone()),
22812282
disable_verify: None,
22822283
},
22832284
..Default::default()
@@ -2304,7 +2305,8 @@ api = "https://api.example.com/access"
23042305
key_dir: Some(format!("{}/keys/", fx.base_url)),
23052306
tls: AuthTls {
23062307
root: vec![fx.ca_pem_path.clone()],
2307-
identity: None,
2308+
cert: None,
2309+
key: None,
23082310
disable_verify: None,
23092311
},
23102312
..Default::default()

0 commit comments

Comments
 (0)