@gjsify/video 0.4.36 → 0.4.38
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/video-bridge.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{Gst as e}from"./gst-init.js";import{buildMediaStreamPipeline as t,buildUriPipeline as n}from"./pipeline-builder.js";import r from"gi://GObject";import i from"gi://GLib?version=2.0";import a from"gi://Gtk?version=4.0";import{attachEventControllers as o}from"@gjsify/event-bridge";import{Event as s}from"@gjsify/dom-events";import{BridgeEnvironment as c}from"@gjsify/bridge-types";import{HTMLVideoElement as l,notifyElementResize as u}from"@gjsify/dom-elements";const d=`media-playback-start-symbolic`,f=`media-playback-pause-symbolic`;function formatTime(e){return!isFinite(e)||isNaN(e)?`--:--`:`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,`0`)}`}const p=r.registerClass({GTypeName:`GjsifyVideoBridge`},class VideoBridge extends a.Box{constructor(e){super({...e,orientation:a.Orientation.VERTICAL}),this._timeOrigin=i.get_monotonic_time(),this._pipeline=null,this._pipelineBus=null,this._pipelineBusHandlers=[],this._readyCallbacks=[],this._resizeCallbacks=[],this._ready=!1,this._controls=null,this._positionTimerId=null,this._updatingFromTimer=!1,this._hideTimerId=null,this._overlay=new a.Overlay({hexpand:!0,vexpand:!0}),this.append(this._overlay),this._picture=new a.Picture({hexpand:!0,vexpand:!0}),this._overlay.set_child(this._picture),this._video=new l;let t={performanceNow:()=>(i.get_monotonic_time()-this._timeOrigin)/1e3,getWidth:()=>this.get_allocated_width(),getHeight:()=>this.get_allocated_height(),getDevicePixelRatio:()=>this.get_native()?.get_surface()?.get_scale_factor()??1};this._environment=new c(t),this._environment.document.body.appendChild(this._video),o(this,()=>this._video),this._video.addEventListener(`srcobjectchange`,()=>this._onSrcObjectChange()),this._video.addEventListener(`srcchange`,()=>this._onSrcChange()),this.connect(`realize`,()=>{if(!this._ready){this._ready=!0;for(let e of this._readyCallbacks)e(this._video);this._readyCallbacks=[]}});let n=0,r=0,checkResize=()=>{let e=this.get_allocated_width(),t=this.get_allocated_height();if(!(e===n&&t===r)){n=e,r=t,this._video.dispatchEvent(new s(`resize`)),u(this._video,e,t);for(let n of this._resizeCallbacks)n(e,t)}};this.connect(`notify::width-request`,checkResize),this.connect(`notify::height-request`,checkResize),this.connect(`map`,checkResize),this.connect(`unrealize`,()=>{this._destroyPipeline(),this._stopPositionTimer(),this._resizeCallbacks=[]})}get element(){return this._video}get videoElement(){return this._video}get environment(){return this._environment}onReady(e){if(this._ready){e(this._video);return}this._readyCallbacks.push(e)}onResize(e){this._resizeCallbacks.push(e)}installGlobals(){if(globalThis.HTMLVideoElement=l,globalThis.performance===void 0){let e=this._timeOrigin;globalThis.performance={now:()=>(i.get_monotonic_time()-e)/1e3,timeOrigin:Date.now()}}}showControls(e=!0){if(e&&!this._controls){this._controls=this._buildControlBar();let{bar:e}=this._controls;e.set_halign(a.Align.FILL),e.set_valign(a.Align.END),e.set_visible(!1),this._overlay.add_overlay(e),this._startPositionTimer(),this._setupAutoHideMotion(e)}else !e&&this._controls&&(this._overlay.remove_overlay(this._controls.bar),this._controls=null,this._stopPositionTimer(),this._hideTimerId!==null&&(i.Source.remove(this._hideTimerId),this._hideTimerId=null))}_setupAutoHideMotion(e){for(let t of[this,e]){let e=new a.EventControllerMotion;e.connect(`motion`,()=>this._revealControls()),e.connect(`enter`,()=>this._revealControls()),t.add_controller(e)}}_revealControls(){this._controls&&(this._controls.bar.set_visible(!0),this._hideTimerId!==null&&i.Source.remove(this._hideTimerId),this._hideTimerId=i.timeout_add_seconds(i.PRIORITY_DEFAULT,2,()=>(this._hideTimerId=null,this._controls?.bar.set_visible(!1),i.SOURCE_REMOVE)))}_buildControlBar(){let e=new a.Box({orientation:a.Orientation.HORIZONTAL,spacing:6,margin_start:6,margin_end:6,margin_top:4,margin_bottom:4});e.add_css_class(`osd`);let t=new a.Button({icon_name:f});t.connect(`clicked`,()=>{this._video.paused?(this._video.play(),t.set_icon_name(f)):(this._video.pause(),t.set_icon_name(d))}),e.append(t);let n=new a.Adjustment({lower:0,upper:1,step_increment:1,page_increment:10}),r=a.Scale.new(a.Orientation.HORIZONTAL,n);r.set_hexpand(!0),r.set_draw_value(!1),r.connect(`change-value`,(e,t,n)=>(!this._updatingFromTimer&&isFinite(n)&&(this._video.currentTime=n),!1)),e.append(r);let i=new a.Label({label:`--:-- / --:--`,use_markup:!1});e.append(i);let o=new a.VolumeButton({value:1});return o.connect(`value-changed`,(e,t)=>{this._video.volume=t}),e.append(o),{bar:e,playBtn:t,seekAdj:n,seekScale:r,timeLabel:i,volumeBtn:o,lastSeekValue:NaN,lastTimeText:``}}_startPositionTimer(){this._positionTimerId===null&&(this._positionTimerId=i.timeout_add(i.PRIORITY_DEFAULT,200,()=>{let e=this._controls;if(!e)return i.SOURCE_REMOVE;let t=this._video.currentTime,n=this._video.duration;isFinite(n)&&n>0&&(e.seekAdj.upper!==n&&(e.seekAdj.upper=n),t!==e.lastSeekValue&&(this._updatingFromTimer=!0,e.seekAdj.set_value(t),this._updatingFromTimer=!1,e.lastSeekValue=t));let r=`${formatTime(t)} / ${formatTime(n)}`;r!==e.lastTimeText&&(e.timeLabel.set_label(r),e.lastTimeText=r);let a=this._video.paused?d:f;return e.playBtn.get_icon_name()!==a&&e.playBtn.set_icon_name(a),i.SOURCE_CONTINUE}))}_stopPositionTimer(){this._positionTimerId!==null&&(i.Source.remove(this._positionTimerId),this._positionTimerId=null)}_onSrcObjectChange(){this._destroyPipeline();let e=this._video.srcObject;if(!e)return;let n=(e.getVideoTracks?.()??[]).find(e=>e._gstSource!=null);if(!n?._gstSource){console.warn(`VideoBridge: MediaStream has no video track with GStreamer source`);return}try{let{pipeline:e,paintable:r,tee:i}=t(n._gstSource,n._gstPipeline);this._attachPipeline(e,r),n._gstPipeline=e,n._gstTee=i}catch(e){console.error(`VideoBridge: Failed to build MediaStream pipeline:`,e)}}_onSrcChange(){if(this._destroyPipeline(),this._video.src)try{let{pipeline:e,paintable:t}=n(this._video.src);this._attachPipeline(e,t)}catch(e){console.error(`VideoBridge: Failed to build URI pipeline:`,e)}}_attachPipeline(t,n){this._pipeline=t,this._video._pipeline=t,this._picture.set_paintable(n);let r=t.get_bus();r&&(r.add_signal_watch(),this._pipelineBus=r,this._pipelineBusHandlers=[r.connect(`message::error`,(e,t)=>{let[n,r]=t.parse_error();console.error(`VideoBridge pipeline error: ${n?.message??`unknown`} (${r??``})`),this._video.dispatchEvent(new s(`error`))}),r.connect(`message::warning`,(e,t)=>{let[n,r]=t.parse_warning();console.warn(`VideoBridge pipeline warning: ${n?.message??`unknown`} (${r??``})`)})]),t.set_state(e.State.PLAYING)===e.StateChangeReturn.FAILURE&&console.error(`VideoBridge: pipeline state change to PLAYING failed`),this._video.readyState=4,this._video.dispatchEvent(new s(`loadedmetadata`)),this._video.dispatchEvent(new s(`canplay`)),this._video.dispatchEvent(new s(`playing`))}_destroyPipeline(){if(this._pipelineBus){for(let e of this._pipelineBusHandlers)try{this._pipelineBus.disconnect(e)}catch{}try{this._pipelineBus.remove_signal_watch()}catch{}this._pipelineBus=null,this._pipelineBusHandlers=[]}if(this._pipeline){try{this._pipeline.set_state(e.State.NULL)}catch{}this._pipeline=null,this._video._pipeline=null}this._picture.set_paintable(null)}});export{p as VideoBridge};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{Gst as e}from"./gst-init.js";import{buildMediaStreamPipeline as t,buildUriPipeline as n}from"./pipeline-builder.js";import r from"gi://GObject";import i from"gi://GLib?version=2.0";import a from"gi://Gtk?version=4.0";import{attachEventControllers as o}from"@gjsify/event-bridge";import{Event as s}from"@gjsify/dom-events";import{BridgeEnvironment as c}from"@gjsify/bridge-types";import{HTMLVideoElement as l,notifyElementResize as u}from"@gjsify/dom-elements";const d=`media-playback-start-symbolic`,f=`media-playback-pause-symbolic`;function formatTime(e){return!isFinite(e)||isNaN(e)?`--:--`:`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,`0`)}`}const p=r.registerClass({GTypeName:`GjsifyVideoBridge`},class VideoBridge extends a.Box{constructor(e){super({...e,orientation:a.Orientation.VERTICAL}),this._timeOrigin=i.get_monotonic_time(),this._pipeline=null,this._pipelineBus=null,this._pipelineBusHandlers=[],this._readyCallbacks=[],this._resizeCallbacks=[],this._ready=!1,this._controls=null,this._positionTimerId=null,this._updatingFromTimer=!1,this._hideTimerId=null,this._overlay=new a.Overlay({hexpand:!0,vexpand:!0}),this.append(this._overlay),this._picture=new a.Picture({hexpand:!0,vexpand:!0}),this._overlay.set_child(this._picture),this._video=new l;let t={performanceNow:()=>(i.get_monotonic_time()-this._timeOrigin)/1e3,getWidth:()=>this.get_allocated_width(),getHeight:()=>this.get_allocated_height(),getDevicePixelRatio:()=>this.get_native()?.get_surface()?.get_scale_factor()??1};this._environment=new c(t),this._environment.document.body.appendChild(this._video),o(this,()=>this._video),this._video.addEventListener(`srcobjectchange`,()=>this._onSrcObjectChange()),this._video.addEventListener(`srcchange`,()=>this._onSrcChange()),this.connect(`realize`,()=>{if(!this._ready){this._ready=!0;for(let e of this._readyCallbacks)e(this._video);this._readyCallbacks=[]}});let n=0,r=0,checkResize=()=>{let e=this.get_allocated_width(),t=this.get_allocated_height();if(!(e===n&&t===r)){n=e,r=t,this._video.dispatchEvent(new s(`resize`)),u(this._video,e,t);for(let n of this._resizeCallbacks)n(e,t)}};this.connect(`notify::width-request`,checkResize),this.connect(`notify::height-request`,checkResize),this.connect(`map`,checkResize),this.connect(`unrealize`,()=>{this._destroyPipeline(),this._stopPositionTimer(),this._resizeCallbacks=[]})}get element(){return this._video}get videoElement(){return this._video}get environment(){return this._environment}onReady(e){if(this._ready){e(this._video);return}this._readyCallbacks.push(e)}onResize(e){this._resizeCallbacks.push(e)}installGlobals(){if(globalThis.HTMLVideoElement=l,globalThis.performance===void 0){let e=this._timeOrigin;globalThis.performance={now:()=>(i.get_monotonic_time()-e)/1e3,timeOrigin:Date.now()}}}showControls(e=!0){if(e&&!this._controls){this._controls=this._buildControlBar();let{bar:e}=this._controls;e.set_halign(a.Align.FILL),e.set_valign(a.Align.END),e.set_visible(!1),this._overlay.add_overlay(e),this._startPositionTimer(),this._setupAutoHideMotion(e)}else !e&&this._controls&&(this._overlay.remove_overlay(this._controls.bar),this._controls=null,this._stopPositionTimer(),this._hideTimerId!==null&&(i.Source.remove(this._hideTimerId),this._hideTimerId=null))}_setupAutoHideMotion(e){for(let t of[this,e]){let e=new a.EventControllerMotion;e.connect(`motion`,()=>this._revealControls()),e.connect(`enter`,()=>this._revealControls()),t.add_controller(e)}}_revealControls(){this._controls&&(this._controls.bar.set_visible(!0),this._hideTimerId!==null&&i.Source.remove(this._hideTimerId),this._hideTimerId=i.timeout_add_seconds(i.PRIORITY_DEFAULT,2,()=>(this._hideTimerId=null,this._controls?.bar.set_visible(!1),i.SOURCE_REMOVE)))}_buildControlBar(){let e=new a.Box({orientation:a.Orientation.HORIZONTAL,spacing:6,margin_start:6,margin_end:6,margin_top:4,margin_bottom:4});e.add_css_class(`osd`);let t=new a.Button({icon_name:f});t.connect(`clicked`,()=>{this._video.paused?(this._video.play(),t.set_icon_name(f)):(this._video.pause(),t.set_icon_name(d))}),e.append(t);let n=new a.Adjustment({lower:0,upper:1,step_increment:1,page_increment:10}),r=a.Scale.new(a.Orientation.HORIZONTAL,n);r.set_hexpand(!0),r.set_draw_value(!1),r.connect(`change-value`,(e,t,n)=>(!this._updatingFromTimer&&isFinite(n)&&(this._video.currentTime=n),!1)),e.append(r);let i=new a.Label({label:`--:-- / --:--`,use_markup:!1});e.append(i);let o=new a.VolumeButton({value:1});return o.connect(`value-changed`,(e,t)=>{this._video.volume=t}),e.append(o),{bar:e,playBtn:t,seekAdj:n,seekScale:r,timeLabel:i,volumeBtn:o,lastSeekValue:NaN,lastTimeText:``}}_startPositionTimer(){this._positionTimerId===null&&(this._positionTimerId=i.timeout_add(i.PRIORITY_DEFAULT,200,()=>{let e=this._controls;if(!e)return i.SOURCE_REMOVE;let t=this._video.currentTime,n=this._video.duration;isFinite(n)&&n>0&&(e.seekAdj.upper!==n&&(e.seekAdj.upper=n),t!==e.lastSeekValue&&(this._updatingFromTimer=!0,e.seekAdj.set_value(t),this._updatingFromTimer=!1,e.lastSeekValue=t));let r=`${formatTime(t)} / ${formatTime(n)}`;r!==e.lastTimeText&&(e.timeLabel.set_label(r),e.lastTimeText=r);let a=this._video.paused?d:f;return e.playBtn.get_icon_name()!==a&&e.playBtn.set_icon_name(a),i.SOURCE_CONTINUE}))}_stopPositionTimer(){this._positionTimerId!==null&&(i.Source.remove(this._positionTimerId),this._positionTimerId=null)}_onSrcObjectChange(){this._destroyPipeline();let e=this._video.srcObject;if(!e)return;let n=(e.getVideoTracks?.()??[]).find(e=>e._gstSource!=null);if(!n?._gstSource){console.warn(`VideoBridge: MediaStream has no video track with GStreamer source`);return}try{let{pipeline:e,paintable:r,tee:i}=t(n._gstSource,n._gstPipeline??null);this._attachPipeline(e,r),n._gstPipeline=e,n._gstTee=i}catch(e){console.error(`VideoBridge: Failed to build MediaStream pipeline:`,e)}}_onSrcChange(){if(this._destroyPipeline(),this._video.src)try{let{pipeline:e,paintable:t}=n(this._video.src);this._attachPipeline(e,t)}catch(e){console.error(`VideoBridge: Failed to build URI pipeline:`,e)}}_attachPipeline(t,n){this._pipeline=t,this._video._pipeline=t,this._picture.set_paintable(n);let r=t.get_bus();r&&(r.add_signal_watch(),this._pipelineBus=r,this._pipelineBusHandlers=[r.connect(`message::error`,(e,t)=>{let[n,r]=t.parse_error();console.error(`VideoBridge pipeline error: ${n?.message??`unknown`} (${r??``})`),this._video.dispatchEvent(new s(`error`))}),r.connect(`message::warning`,(e,t)=>{let[n,r]=t.parse_warning();console.warn(`VideoBridge pipeline warning: ${n?.message??`unknown`} (${r??``})`)})]),t.set_state(e.State.PLAYING)===e.StateChangeReturn.FAILURE&&console.error(`VideoBridge: pipeline state change to PLAYING failed`),this._video.readyState=4,this._video.dispatchEvent(new s(`loadedmetadata`)),this._video.dispatchEvent(new s(`canplay`)),this._video.dispatchEvent(new s(`playing`))}_destroyPipeline(){if(this._pipelineBus){for(let e of this._pipelineBusHandlers)try{this._pipelineBus.disconnect(e)}catch{}try{this._pipelineBus.remove_signal_watch()}catch{}this._pipelineBus=null,this._pipelineBusHandlers=[]}if(this._pipeline){try{this._pipeline.set_state(e.State.NULL)}catch{}this._pipeline=null,this._video._pipeline=null}this._picture.set_paintable(null)}});export{p as VideoBridge};
|
|
@@ -70,7 +70,7 @@ export declare const VideoBridge: {
|
|
|
70
70
|
volumeBtn: Gtk.VolumeButton;
|
|
71
71
|
lastSeekValue: number;
|
|
72
72
|
lastTimeText: string;
|
|
73
|
-
}>;
|
|
73
|
+
} | null>;
|
|
74
74
|
_startPositionTimer(): void;
|
|
75
75
|
_stopPositionTimer(): void;
|
|
76
76
|
_onSrcObjectChange(): void;
|
|
@@ -530,7 +530,7 @@ export declare const VideoBridge: {
|
|
|
530
530
|
volumeBtn: Gtk.VolumeButton;
|
|
531
531
|
lastSeekValue: number;
|
|
532
532
|
lastTimeText: string;
|
|
533
|
-
}>;
|
|
533
|
+
} | null>;
|
|
534
534
|
_startPositionTimer(): void;
|
|
535
535
|
_stopPositionTimer(): void;
|
|
536
536
|
_onSrcObjectChange(): void;
|
|
@@ -990,7 +990,7 @@ export declare const VideoBridge: {
|
|
|
990
990
|
volumeBtn: Gtk.VolumeButton;
|
|
991
991
|
lastSeekValue: number;
|
|
992
992
|
lastTimeText: string;
|
|
993
|
-
}>;
|
|
993
|
+
} | null>;
|
|
994
994
|
_startPositionTimer(): void;
|
|
995
995
|
_stopPositionTimer(): void;
|
|
996
996
|
_onSrcObjectChange(): void;
|
|
@@ -1450,7 +1450,7 @@ export declare const VideoBridge: {
|
|
|
1450
1450
|
volumeBtn: Gtk.VolumeButton;
|
|
1451
1451
|
lastSeekValue: number;
|
|
1452
1452
|
lastTimeText: string;
|
|
1453
|
-
}>;
|
|
1453
|
+
} | null>;
|
|
1454
1454
|
_startPositionTimer(): void;
|
|
1455
1455
|
_stopPositionTimer(): void;
|
|
1456
1456
|
_onSrcObjectChange(): void;
|
|
@@ -1910,7 +1910,7 @@ export declare const VideoBridge: {
|
|
|
1910
1910
|
volumeBtn: Gtk.VolumeButton;
|
|
1911
1911
|
lastSeekValue: number;
|
|
1912
1912
|
lastTimeText: string;
|
|
1913
|
-
}>;
|
|
1913
|
+
} | null>;
|
|
1914
1914
|
_startPositionTimer(): void;
|
|
1915
1915
|
_stopPositionTimer(): void;
|
|
1916
1916
|
_onSrcObjectChange(): void;
|
|
@@ -2370,7 +2370,7 @@ export declare const VideoBridge: {
|
|
|
2370
2370
|
volumeBtn: Gtk.VolumeButton;
|
|
2371
2371
|
lastSeekValue: number;
|
|
2372
2372
|
lastTimeText: string;
|
|
2373
|
-
}>;
|
|
2373
|
+
} | null>;
|
|
2374
2374
|
_startPositionTimer(): void;
|
|
2375
2375
|
_stopPositionTimer(): void;
|
|
2376
2376
|
_onSrcObjectChange(): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/video",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.38",
|
|
4
4
|
"description": "VideoBridge — GTK container for HTMLVideoElement backed by GStreamer gtk4paintablesink",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -36,22 +36,23 @@
|
|
|
36
36
|
"@girs/gobject-2.0": "2.88.0-4.0.4",
|
|
37
37
|
"@girs/gst-1.0": "1.28.1-4.0.4",
|
|
38
38
|
"@girs/gtk-4.0": "4.23.0-4.0.4",
|
|
39
|
-
"@gjsify/bridge-types": "^0.4.
|
|
40
|
-
"@gjsify/dom-elements": "^0.4.
|
|
41
|
-
"@gjsify/dom-events": "^0.4.
|
|
42
|
-
"@gjsify/dom-exception": "^0.4.
|
|
43
|
-
"@gjsify/event-bridge": "^0.4.
|
|
39
|
+
"@gjsify/bridge-types": "^0.4.38",
|
|
40
|
+
"@gjsify/dom-elements": "^0.4.38",
|
|
41
|
+
"@gjsify/dom-events": "^0.4.38",
|
|
42
|
+
"@gjsify/dom-exception": "^0.4.38",
|
|
43
|
+
"@gjsify/event-bridge": "^0.4.38"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@gjsify/cli": "^0.4.
|
|
46
|
+
"@gjsify/cli": "^0.4.38",
|
|
47
47
|
"@types/node": "^25.9.1",
|
|
48
|
-
"typescript": "^
|
|
48
|
+
"typescript": "^6.0.3"
|
|
49
49
|
},
|
|
50
50
|
"gjsify": {
|
|
51
51
|
"runtimes": {
|
|
52
52
|
"gjs": "polyfill",
|
|
53
53
|
"node": "none",
|
|
54
|
-
"browser": "none"
|
|
54
|
+
"browser": "none",
|
|
55
|
+
"nativescript": "none"
|
|
55
56
|
}
|
|
56
57
|
},
|
|
57
58
|
"license": "MIT",
|