@gjsify/webaudio 0.51.1 → 0.53.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/README.md CHANGED
@@ -36,6 +36,31 @@ gain.connect(ctx.destination);
36
36
  source.start();
37
37
  ```
38
38
 
39
+ ## Audio output selection
40
+
41
+ On `ensureGstInit()` (the first `AudioContext`, `decodeAudioData`, or any
42
+ other GStreamer-touching call), this package sets the `openalsink` GStreamer
43
+ plugin feature's rank to `Gst.Rank.NONE` in the **process-wide** GStreamer
44
+ registry — it affects every pipeline in the process, including ones built
45
+ outside this package.
46
+
47
+ Why: `autoaudiosink` (the element behind `AudioContext` playback) tries
48
+ registered audio sinks in rank order until one opens. `openalsink` is the
49
+ one candidate whose `open()` does not fail fast: on a host with no
50
+ reachable PipeWire/Pulse/ALSA, OpenAL Soft's device backend runs its own
51
+ nested connection probe synchronously inside the GStreamer state change,
52
+ which can stall the whole process for tens of seconds (measured in CI —
53
+ `[ALSOFT] Failed to connect PipeWire` followed by 30+ seconds of silence).
54
+ `autoaudiosink` already falls back to a silent `fakesink` when nothing
55
+ opens, in well under 100ms — deranking `openalsink` restores that existing
56
+ fallback instead of leaving it reachable through the one candidate that
57
+ defeats it.
58
+
59
+ Set `GJSIFY_GST_KEEP_OPENAL=1` to opt out, if a host genuinely needs OpenAL
60
+ Soft as its audio backend. This also un-deranks `openalsrc`/`openalsink`
61
+ for `@gjsify/webrtc` if both are loaded in the same process — the two
62
+ packages share the one GStreamer registry.
63
+
39
64
  ## License
40
65
 
41
66
  MIT
@@ -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)`)}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
+ import"./_virtual/_rolldown/runtime.js";import e from"gi://GLib?version=2.0";import t from"gi://Gst?version=1.0";import n from"gi://GstApp?version=1.0";let r=!1;function ensureGstAppLoaded(){if(n.AppSrc===void 0)throw Error(`GstApp typelib is unavailable — install gstreamer1-plugins-base (gst-plugins-base)`)}const i=[`openalsink`];function excludeUnboundedAudioSinkCandidates(n=e.getenv(`GJSIFY_GST_KEEP_OPENAL`)===`1`){if(n)return;let r=t.Registry.get();for(let e of i)r.lookup_feature(e)?.set_rank(t.Rank.NONE)}const defaultInitializer=()=>{t.init(null),ensureGstAppLoaded(),excludeUnboundedAudioSinkCandidates()};let a=`pending`;function tryEnsureGstInit(e=defaultInitializer){let t=e===defaultInitializer;if(t&&a!==`pending`)return a===`ready`?null:a.failed;try{return e(),t&&(a=`ready`,r=!0),null}catch(e){let n=e instanceof Error?e.message:String(e);return t&&(a={failed:n}),n}}function primeGstOutcomeForTests(e){if(e===void 0){a=`pending`,r=!1;return}a=e===null?`ready`:{failed:e},r=e===null}function ensureGstInit(){if(r)return;let e=tryEnsureGstInit();if(e!==null)throw Error(e)}export{t as Gst,ensureGstInit,excludeUnboundedAudioSinkCandidates,primeGstOutcomeForTests,tryEnsureGstInit};
@@ -1,4 +1,6 @@
1
1
  import Gst from 'gi://Gst?version=1.0';
2
+ /** TEST SEAM (exported) — see the `keepOpenal` parameter doc above. */
3
+ export declare function excludeUnboundedAudioSinkCandidates(keepOpenal?: boolean): void;
2
4
  /** The GStreamer bring-up. A parameter so its FAILURE branch is executable. */
3
5
  export type GstInitializer = () => void;
4
6
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/webaudio",
3
- "version": "0.51.1",
3
+ "version": "0.53.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,18 +42,18 @@
42
42
  "audio-api"
43
43
  ],
44
44
  "dependencies": {
45
- "@gjsify/dom-events": "^0.51.1"
45
+ "@gjsify/dom-events": "^0.53.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@girs/gio-2.0": "5.0.0",
49
- "@girs/gjs": "5.0.0",
50
- "@girs/glib-2.0": "5.0.0",
51
- "@girs/gst-1.0": "5.0.0",
52
- "@girs/gstapp-1.0": "5.0.0",
53
- "@girs/gstaudio-1.0": "5.0.0",
54
- "@girs/gstbase-1.0": "5.0.0",
55
- "@gjsify/cli": "^0.51.1",
56
- "@gjsify/unit": "^0.51.1",
48
+ "@girs/gio-2.0": "5.4.0",
49
+ "@girs/gjs": "5.4.0",
50
+ "@girs/glib-2.0": "5.4.0",
51
+ "@girs/gst-1.0": "5.4.0",
52
+ "@girs/gstapp-1.0": "5.4.0",
53
+ "@girs/gstaudio-1.0": "5.4.0",
54
+ "@girs/gstbase-1.0": "5.4.0",
55
+ "@gjsify/cli": "^0.53.0",
56
+ "@gjsify/unit": "^0.53.0",
57
57
  "@types/node": "^25.9.2",
58
58
  "typescript": "^6.0.3"
59
59
  },