@gjsify/webaudio 0.32.0 → 0.34.0
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/lib/esm/audio-context.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{AudioNode as e}from"./audio-node.js";import{
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{AudioNode as e}from"./audio-node.js";import{tryEnsureGstInit as t}from"./gst-init.js";import{stopAllPipelines as n}from"./gst-teardown.js";import{GainNode as r}from"./gain-node.js";import{AudioBufferSourceNode as i}from"./audio-buffer-source-node.js";import{AudioBuffer as a}from"./audio-buffer.js";import{AudioDestinationNode as o}from"./audio-destination-node.js";import{decodeAudioDataSync as s}from"./gst-decoder.js";import c from"gi://GLib?version=2.0";var AudioContext=class{state=`suspended`;sampleRate=44100;destination;listener={};_startTime;constructor(){let e=t();e!==null&&console.warn(`[webaudio] AudioContext: GStreamer is unavailable, continuing SILENT — ${e}\n Audio needs GStreamer 1.0 with gst-plugins-base. The @gjsify/gtk-runtime-* bundles do not ship it, so install it system-wide (Fedora: gstreamer1 gstreamer1-plugins-base; Windows: an MSYS2/gvsbuild GStreamer on PATH).`),this._startTime=c.get_monotonic_time(),this.destination=new o}get currentTime(){return(c.get_monotonic_time()-this._startTime)/1e6}createGain(){return new r}createBufferSource(){return new i}createBuffer(e,t,n){return new a({numberOfChannels:e,length:t,sampleRate:n})}decodeAudioData(e,t,n){try{let n=s(e);return t?.(n),Promise.resolve(n)}catch(e){let t=e instanceof DOMException?e:new DOMException(`Unable to decode audio data`,`EncodingError`);return n?.(t),Promise.reject(t)}}async resume(){this.state=`running`}async suspend(){this.state=`suspended`}async close(){this.state=`closed`,n()}createAnalyser(){return{connect:()=>{},disconnect:()=>{},fftSize:2048,frequencyBinCount:1024,getByteFrequencyData:()=>{},getFloatFrequencyData:()=>{}}}createDynamicsCompressor(){return new e}createBiquadFilter(){return new e}createConvolver(){return new e}createPanner(){return new e}createStereoPanner(){return new e}addEventListener(e,t){}removeEventListener(e,t){}};export{AudioContext};
|
package/lib/esm/gst-init.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import e from"gi://Gst?version=1.0";import t from"gi://GstApp?version=1.0";let n=!1;function ensureGstAppLoaded(){if(t.AppSrc===void 0)throw Error(`GstApp typelib is unavailable — install gstreamer1-plugins-base (gst-plugins-base)`)}
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import e from"gi://Gst?version=1.0";import t from"gi://GstApp?version=1.0";let n=!1;function ensureGstAppLoaded(){if(t.AppSrc===void 0)throw Error(`GstApp typelib is unavailable — install gstreamer1-plugins-base (gst-plugins-base)`)}const defaultInitializer=()=>{e.init(null),ensureGstAppLoaded()};let r=`pending`;function tryEnsureGstInit(e=defaultInitializer){let t=e===defaultInitializer;if(t&&r!==`pending`)return r===`ready`?null:r.failed;try{return e(),t&&(r=`ready`,n=!0),null}catch(e){let n=e instanceof Error?e.message:String(e);return t&&(r={failed:n}),n}}function primeGstOutcomeForTests(e){if(e===void 0){r=`pending`,n=!1;return}r=e===null?`ready`:{failed:e},n=e===null}function ensureGstInit(){if(n)return;let e=tryEnsureGstInit();if(e!==null)throw Error(e)}export{e as Gst,ensureGstInit,primeGstOutcomeForTests,tryEnsureGstInit};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{Gst as e,
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{Gst as e,tryEnsureGstInit as t}from"./gst-init.js";import{stopPipeline as n,trackPipeline as r}from"./gst-teardown.js";const i=new Set([`audio/mpeg`,`audio/mp3`,`audio/wav`,`audio/x-wav`,`audio/ogg`,`audio/webm`,`audio/flac`,`audio/x-flac`,`audio/aac`,`audio/mp4`]);var HTMLAudioElement=class{src=``;volume=1;loop=!1;paused=!0;currentTime=0;duration=0;readyState=0;_pipeline=null;canPlayType(e){let t=e.split(`;`)[0].trim().toLowerCase();return i.has(t)?`maybe`:``}play(){if(!this.src)return Promise.resolve();let n=t();return n===null?(this._cleanup(),this._pipeline=e.ElementFactory.make(`playbin`,`player`),this._pipeline?(r(this._pipeline),this._pipeline.set_property(`uri`,this.src),this._pipeline.set_property(`volume`,this.volume),this._pipeline.set_state(e.State.PLAYING),this.paused=!1,Promise.resolve()):Promise.resolve()):(console.warn(`[webaudio] Audio.play: GStreamer is unavailable, staying silent — ${n}`),Promise.resolve())}pause(){this._pipeline&&(this._pipeline.set_state(e.State.PAUSED),this.paused=!0)}load(){this._cleanup()}addEventListener(e,t){}removeEventListener(e,t){}_cleanup(){this._pipeline&&=(n(this._pipeline),null)}};export{HTMLAudioElement};
|
|
@@ -9,6 +9,27 @@ export declare class AudioContext {
|
|
|
9
9
|
readonly destination: AudioDestinationNode;
|
|
10
10
|
readonly listener: {};
|
|
11
11
|
private _startTime;
|
|
12
|
+
/**
|
|
13
|
+
* CONSTRUCTING A CONTEXT IS NOT PLAYING AUDIO, so a missing audio backend
|
|
14
|
+
* may not be fatal here. `ensureGstInit()` threw, and it killed whole
|
|
15
|
+
* applications: on the batteries-included GTK runtime bundles (win32-x64,
|
|
16
|
+
* darwin) GStreamer is not shipped, and Excalibur's boot-time audio unlock
|
|
17
|
+
* constructs a context before the first frame — so `gjsify showcase
|
|
18
|
+
* excalibur-jelly-jumper --runtime node` on Windows died with "Failed to
|
|
19
|
+
* require Gst 1.0: Typelib file for namespace 'Gst' not found" and the game
|
|
20
|
+
* never rendered.
|
|
21
|
+
*
|
|
22
|
+
* In a browser `new AudioContext()` always succeeds; a page that cannot play
|
|
23
|
+
* sound still runs. This matches that. The rule was already written down one
|
|
24
|
+
* level below — `AudioBufferSourceNode.start()` degrades to silent rather
|
|
25
|
+
* than throw, "a single failed audio node must NEVER crash the whole app" —
|
|
26
|
+
* it just had not been applied to the constructor.
|
|
27
|
+
*
|
|
28
|
+
* Warned ONCE per context and not per sound: a game loading forty samples
|
|
29
|
+
* would otherwise bury its own output. Everything downstream already copes —
|
|
30
|
+
* `start()` degrades to silent and `decodeAudioData` rejects with an
|
|
31
|
+
* `EncodingError`, which is what the spec says a failed decode does.
|
|
32
|
+
*/
|
|
12
33
|
constructor();
|
|
13
34
|
/** Monotonically increasing time in seconds since context creation. */
|
|
14
35
|
get currentTime(): number;
|
package/lib/types/gst-init.d.ts
CHANGED
|
@@ -1,3 +1,42 @@
|
|
|
1
1
|
import Gst from 'gi://Gst?version=1.0';
|
|
2
|
+
/** The GStreamer bring-up. A parameter so its FAILURE branch is executable. */
|
|
3
|
+
export type GstInitializer = () => void;
|
|
4
|
+
/**
|
|
5
|
+
* Bring GStreamer up and REPORT the outcome instead of throwing.
|
|
6
|
+
*
|
|
7
|
+
* Returns `null` on success, or a human-readable reason. Every caller that can
|
|
8
|
+
* carry on without audio should use this one — see `AudioContext`.
|
|
9
|
+
*
|
|
10
|
+
* `initializer` is injectable for the same reason `dirLinkTarget` takes its link
|
|
11
|
+
* kind: the interesting branch here is the one where GStreamer is ABSENT, and on
|
|
12
|
+
* a developer's Linux box it never is. A branch nobody can execute is how the
|
|
13
|
+
* throwing version below shipped as the only entry point.
|
|
14
|
+
*
|
|
15
|
+
* The memo applies to the DEFAULT initializer only. A test passing its own is
|
|
16
|
+
* asking to exercise one specific outcome, and must neither be answered from the
|
|
17
|
+
* process-wide memo nor poison it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function tryEnsureGstInit(initializer?: GstInitializer): string | null;
|
|
20
|
+
/**
|
|
21
|
+
* TEST SEAM — answer the next bring-up with `reason` (or `null` for success)
|
|
22
|
+
* without touching the real GStreamer, and `undefined` to forget again.
|
|
23
|
+
*
|
|
24
|
+
* The injectable initializer above covers `tryEnsureGstInit` itself, but not its
|
|
25
|
+
* CALLERS: `new AudioContext()` has no initializer to hand it, and "constructing
|
|
26
|
+
* a context on a host with no GStreamer does not throw" is the exact property
|
|
27
|
+
* whose absence killed the game. Priming the memo is what lets that be asserted
|
|
28
|
+
* on a developer machine, where GStreamer is always installed.
|
|
29
|
+
*/
|
|
30
|
+
export declare function primeGstOutcomeForTests(reason: string | null | undefined): void;
|
|
31
|
+
/**
|
|
32
|
+
* Bring GStreamer up, or throw.
|
|
33
|
+
*
|
|
34
|
+
* For the callers that genuinely cannot proceed without it — decoding bytes,
|
|
35
|
+
* building a playback pipeline. Constructing an `AudioContext` is NOT one of
|
|
36
|
+
* them, and treating it as one is what killed whole applications: on the
|
|
37
|
+
* batteries-included GTK runtime bundles (win32-x64, darwin) GStreamer is not
|
|
38
|
+
* shipped at all, so `new AudioContext()` threw "Failed to require Gst 1.0"
|
|
39
|
+
* during Excalibur's boot-time audio unlock and the game never rendered a frame.
|
|
40
|
+
*/
|
|
2
41
|
export declare function ensureGstInit(): void;
|
|
3
42
|
export { Gst };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/webaudio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "Web Audio API for GJS using GStreamer as audio backend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"audio-api"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@gjsify/dom-events": "^0.
|
|
45
|
+
"@gjsify/dom-events": "^0.34.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@girs/gio-2.0": "^4.1.0",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"@girs/gstapp-1.0": "^4.1.0",
|
|
53
53
|
"@girs/gstaudio-1.0": "^4.1.0",
|
|
54
54
|
"@girs/gstbase-1.0": "^4.1.0",
|
|
55
|
-
"@gjsify/cli": "^0.
|
|
56
|
-
"@gjsify/unit": "^0.
|
|
55
|
+
"@gjsify/cli": "^0.34.0",
|
|
56
|
+
"@gjsify/unit": "^0.34.0",
|
|
57
57
|
"@types/node": "^25.9.2",
|
|
58
58
|
"typescript": "^6.0.3"
|
|
59
59
|
},
|