ink-framework-audio 0.1.0-alpha.12 → 0.1.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "ink-framework-audio",
3
- "version": "0.1.0-alpha.12",
3
+ "version": "0.1.0-alpha.13",
4
4
  "exports": {
5
5
  ".": "./src/index.ts",
6
6
  "./microphone": "./src/microphone.ts",
7
7
  "./recording": "./src/recording.ts"
8
8
  },
9
9
  "peerDependencies": {
10
- "@ink/files": "npm:ink-framework-files@0.1.0-alpha.12",
11
- "ink": "npm:ink-framework@0.1.0-alpha.12",
10
+ "@ink/files": "npm:ink-framework-files@0.1.0-alpha.13",
11
+ "ink": "npm:ink-framework@0.1.0-alpha.13",
12
12
  "react": "19.2.8"
13
13
  },
14
14
  "license": "MIT",
@@ -20,6 +20,7 @@
20
20
  "files": [
21
21
  "src",
22
22
  "*.json",
23
- "*.ts"
23
+ "*.ts",
24
+ "*.md"
24
25
  ]
25
26
  }
@@ -1,7 +1,7 @@
1
- import { createElement, useEffect, useMemo, useRef, useState } from "react";
1
+ import { createElement, useEffect, useMemo, useState } from "ink/internal/react";
2
2
  import type { Snapshot, SnapshotSource } from "ink";
3
3
  import { NativeError } from "ink/native";
4
- import { attachNativeController } from "ink/native/controller";
4
+ import { useNativeController } from "ink/internal/controller";
5
5
 
6
6
  const displayController = Symbol("captureController");
7
7
  export type CaptureDisplay = { readonly [displayController]: number | null };
@@ -48,7 +48,7 @@ export function useCapture<State extends { status: string; error: Error | null }
48
48
  ) {
49
49
  const [state, setState] = useState(() => selectStatus(initial));
50
50
  const [id, setId] = useState<number | null>(null);
51
- const controller = useRef<ReturnType<typeof attachNativeController> | null>(null);
51
+ const controller = useNativeController("audio", "audio capture");
52
52
  const channel = useMemo(() => {
53
53
  let snapshot: Snapshot<State> = { status: "loading" };
54
54
  const listeners = new Set<() => void>();
@@ -75,7 +75,7 @@ export function useCapture<State extends { status: string; error: Error | null }
75
75
  },
76
76
  };
77
77
  return { source, publish, observe };
78
- }, []);
78
+ }, [controller]);
79
79
  useEffect(() => {
80
80
  setState(selectStatus(initial));
81
81
  setId(null);
@@ -92,27 +92,18 @@ export function useCapture<State extends { status: string; error: Error | null }
92
92
  setState({ ...selectStatus(initial), status: "error", error: failure });
93
93
  channel.publish({ status: "error", error: failure });
94
94
  };
95
- const attachment = attachNativeController("audio", { kind, config: referenceHz === undefined ? {} : { referenceHz } }, value => {
96
- if (controller.current !== attachment) return;
95
+ return controller.attach({ kind, config: referenceHz === undefined ? {} : { referenceHz } }, value => {
97
96
  try { publish(decode(value)); }
98
97
  catch (error) { fail(error); }
98
+ }, fail, id => {
99
+ setId(id);
100
+ channel.observe();
99
101
  });
100
- controller.current = attachment;
101
- void attachment.ready.then(() => {
102
- if (controller.current === attachment) {
103
- setId(attachment.id);
104
- channel.observe();
105
- }
106
- }, error => { if (controller.current === attachment) fail(error); });
107
- return () => {
108
- controller.current = null;
109
- void attachment.dispose().catch(error => console.error("Could not release audio capture", error));
110
- };
111
- }, [kind, initial, decode, selectStatus, referenceHz, channel]);
102
+ }, [kind, initial, decode, selectStatus, referenceHz, channel, controller]);
112
103
  const call = useMemo(() => async (operation: string) => {
113
104
  if (!controller.current) throw new NativeError("unavailable", "Audio capture is not attached");
114
105
  return controller.current.call(operation);
115
- }, []);
106
+ }, [controller]);
116
107
  const display = useMemo(() => ({ [displayController]: id }), [id]);
117
108
  return { state, ready: id !== null, call, display, measurements: channel.source };
118
109
  }
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { useEffect, useMemo, useRef, useState } from "react";
2
- import { attachNativeController } from "ink/native/controller";
1
+ import { useEffect, useMemo, useRef, useState } from "ink/internal/react";
2
+ import { useNativeController } from "ink/internal/controller";
3
3
  import { NativeError } from "ink/native";
4
4
  import { playbackController } from "ink/internal/playback";
5
5
 
@@ -137,24 +137,21 @@ export function usePlayer(options: PlayerOptions = {}) {
137
137
  if (!Number.isSafeInteger(startupBuffer) || startupBuffer < 0 || startupBuffer > 30_000) throw new RangeError("Startup buffering must be between 0 and 30000 milliseconds");
138
138
  const [state, setState] = useState(initial);
139
139
  const current = useRef(initial);
140
- const controller = useRef<ReturnType<typeof attachNativeController> | null>(null);
140
+ const controller = useNativeController("audio", "audio player");
141
141
  useEffect(() => {
142
142
  const publish = (next: PlayerState) => { current.current = next; setState(next); };
143
143
  publish(initial);
144
- const attachment = attachNativeController("audio", { kind: "player", config: { session, playback: mode, usage, cache, preloadNext, startupBuffer } }, value => {
144
+ const detach = controller.attach({ kind: "player", config: { session, playback: mode, usage, cache, preloadNext, startupBuffer } }, value => {
145
145
  try { publish(decode(value)); }
146
146
  catch (error) { publish({ ...initial, error: error instanceof Error ? error : new Error(String(error)) }); }
147
- });
148
- controller.current = attachment;
149
- void attachment.ready.catch(error => {
150
- if (controller.current === attachment) publish({ ...initial, error: error instanceof Error ? error : new Error(String(error)) });
147
+ }, error => {
148
+ publish({ ...initial, error: error instanceof Error ? error : new Error(String(error)) });
151
149
  });
152
150
  return () => {
153
- controller.current = null;
151
+ detach();
154
152
  current.current = initial;
155
- void attachment.dispose().catch(error => console.error("Could not release audio player", error));
156
153
  };
157
- }, [session, mode, usage, cache, preloadNext, startupBuffer]);
154
+ }, [session, mode, usage, cache, preloadNext, startupBuffer, controller]);
158
155
  const commands = useMemo(() => {
159
156
  const call = async (operation: string, payload: unknown = {}) => {
160
157
  if (!controller.current || !current.current.ready) throw new NativeError("unavailable", "Audio player is not ready");
@@ -224,6 +221,6 @@ export function usePlayer(options: PlayerOptions = {}) {
224
221
  return call("seekTo", { value: position });
225
222
  },
226
223
  };
227
- }, []);
224
+ }, [controller]);
228
225
  return { state, [playbackController]: controller.current?.id, ...commands };
229
226
  }
package/src/microphone.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { createElement, useMemo } from "react";
1
+ import { createElement, useMemo } from "ink/internal/react";
2
2
  import { NativeError } from "ink/native";
3
3
  import { captureReadout, fields, useCapture, type CaptureDisplay } from "./capture-internal";
4
4
 
package/src/recording.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { useMemo } from "react";
1
+ import { useMemo } from "ink/internal/react";
2
2
  import { NativeError } from "ink/native";
3
3
  import type { FileRef } from "@ink/files";
4
4
  import { captureReadout, fields, useCapture, type CaptureDisplay } from "./capture-internal";