homegames-client 0.2.2 → 0.2.4
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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homegames-client",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Embeddable browser client for Homegames",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"browser": "dist/homegames-client.js",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"buffer": "^6.0.3",
|
|
16
|
-
"homegames-common": "1.7.
|
|
16
|
+
"homegames-common": "1.7.7",
|
|
17
17
|
"homepad": "0.2.1",
|
|
18
18
|
"qrcode-generator": "^2.0.4",
|
|
19
19
|
"squish-150": "npm:squishjs@1.5.0",
|
package/src/media-client.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const RecordingClient = require('./recording-client');
|
|
4
4
|
class MediaClient {
|
|
5
5
|
constructor({ container, assets, send, platform, publish = () => {}, unpublish = () => {} }) {
|
|
6
|
-
Object.assign(this, { container, assets, send, publish, unpublish });
|
|
6
|
+
Object.assign(this, { container, assets, send, platform, publish, unpublish });
|
|
7
7
|
this.streams = new Map(); this.received = new Map(); this.pending = new Map(); this.held = new Set();
|
|
8
8
|
this.recorder = new RecordingClient({ container, send, platform,
|
|
9
9
|
busy: () => this.pending.size || [...this.streams.values()].some(a => a.local) });
|
|
@@ -19,6 +19,7 @@ class MediaClient {
|
|
|
19
19
|
if (this.held.size) return;
|
|
20
20
|
for (const asset of this.streams.values()) if (asset.local && asset.pushToTalk) {
|
|
21
21
|
asset.transmitting = false; asset.data.getTracks().forEach(track => { track.enabled = false; });
|
|
22
|
+
asset.capture?.setTransmitting(false);
|
|
22
23
|
this.send({ type: 'media', action: 'released', id: asset.id });
|
|
23
24
|
}
|
|
24
25
|
this.assets._notifyReady();
|
|
@@ -41,6 +42,7 @@ class MediaClient {
|
|
|
41
42
|
this.send({ type: 'media', action: 'released', id: info.id });
|
|
42
43
|
}
|
|
43
44
|
existing.data.getTracks().forEach(track => { track.enabled = existing.transmitting; });
|
|
45
|
+
existing.capture?.setTransmitting(existing.transmitting);
|
|
44
46
|
}
|
|
45
47
|
} else this.streams.set(info.id, { ...info, type: 'stream', data: this.received.get(info.sourceId), local: false });
|
|
46
48
|
this.assets._notifyReady();
|
|
@@ -56,6 +58,7 @@ class MediaClient {
|
|
|
56
58
|
if (this.recorder.active || this.pending.size || [...this.streams.values()].some(a => a.local)) {
|
|
57
59
|
this.send({ type: 'media', action: 'result', id: info.id, error: 'A microphone/camera is already active or awaiting permission' }); return;
|
|
58
60
|
}
|
|
61
|
+
if (this.platform?.captureLive) return this.requestPortable(info);
|
|
59
62
|
const dialog = document.createElement('dialog');
|
|
60
63
|
dialog.setAttribute('aria-label', 'Enable live media');
|
|
61
64
|
dialog.style.cssText = 'margin:auto;padding:24px;max-width:360px;border:1px solid #666;border-radius:16px;background:#202321;color:white;font:16px system-ui';
|
|
@@ -91,6 +94,30 @@ class MediaClient {
|
|
|
91
94
|
};
|
|
92
95
|
dialog.showModal(); start.focus();
|
|
93
96
|
}
|
|
97
|
+
requestPortable(info) {
|
|
98
|
+
let capture;
|
|
99
|
+
try { capture = this.platform.captureLive(info); }
|
|
100
|
+
catch (error) { this.send({ type: 'media', action: 'result', id: info.id, error: error.message }); return; }
|
|
101
|
+
this.pending.set(info.id, capture);
|
|
102
|
+
capture.result.then(stream => {
|
|
103
|
+
if (this.closed || this.pending.get(info.id) !== capture) { capture.close(); return; }
|
|
104
|
+
this.pending.delete(info.id);
|
|
105
|
+
const asset = { ...info, sourceId: stream.id, type: 'stream', data: stream, local: true, capture,
|
|
106
|
+
transmitting: !!info.transmitting && (!info.pushToTalk || this.held.size > 0) };
|
|
107
|
+
this.streams.set(info.id, asset);
|
|
108
|
+
capture.onended = () => this.stopLocal(info.id);
|
|
109
|
+
capture.onrelease = () => this.release();
|
|
110
|
+
stream.getTracks().forEach(track => { track.enabled = asset.transmitting; });
|
|
111
|
+
capture.setTransmitting(asset.transmitting);
|
|
112
|
+
this.send({ type: 'media', action: 'result', id: info.id, sourceId: stream.id });
|
|
113
|
+
this.publish(info.id, stream); this.assets._notifyReady();
|
|
114
|
+
if (asset.pushToTalk && !asset.transmitting) this.send({ type: 'media', action: 'released', id: info.id });
|
|
115
|
+
}, error => {
|
|
116
|
+
if (this.pending.get(info.id) !== capture) return;
|
|
117
|
+
this.pending.delete(info.id);
|
|
118
|
+
if (!this.closed) this.send({ type: 'media', action: 'result', id: info.id, error: error.message });
|
|
119
|
+
});
|
|
120
|
+
}
|
|
94
121
|
showStop() {
|
|
95
122
|
if (this.stopButton) return;
|
|
96
123
|
const button = this.stopButton = document.createElement('button');
|
|
@@ -102,10 +129,11 @@ class MediaClient {
|
|
|
102
129
|
stopLocal(id) { this.remove(id); this.send({ type: 'media', action: 'stopped', id }); }
|
|
103
130
|
remove(id) {
|
|
104
131
|
const dialog = this.pending.get(id);
|
|
105
|
-
if (dialog) { this.pending.delete(id); dialog.close(); dialog.remove(); }
|
|
132
|
+
if (dialog) { this.pending.delete(id); dialog.close(); dialog.remove?.(); }
|
|
106
133
|
const asset = this.streams.get(id); this.streams.delete(id);
|
|
107
134
|
if (asset?.local) {
|
|
108
135
|
this.unpublish(id);
|
|
136
|
+
if (asset.capture) { asset.capture.onended = null; asset.capture.close(); }
|
|
109
137
|
asset.data.getTracks().forEach(track => { track.onended = null; track.stop(); });
|
|
110
138
|
this.stopButton?.remove(); this.stopButton = null;
|
|
111
139
|
}
|
package/src/portable-project.js
CHANGED
|
@@ -29,7 +29,8 @@ module.exports = {
|
|
|
29
29
|
require('homegames-common/exports-viewer').createExportsViewer,
|
|
30
30
|
require('homegames-common/video-recording').recordVideo,
|
|
31
31
|
require('homegames-common/player-toolbar').createPlayerToolbar,
|
|
32
|
-
{ ...settings, profile: require('homegames-common/player-identity').profile(window)
|
|
32
|
+
{ ...settings, profile: require('homegames-common/player-identity').profile(window),
|
|
33
|
+
createLiveMediaBridge: require('homegames-common/live-media-bridge').createLiveMediaBridge });
|
|
33
34
|
return { ...savesHost, get stopped() { return savesHost.stopped; },
|
|
34
35
|
command: clientHost.command, downloadGame: clientHost.download,
|
|
35
36
|
close: async () => { clientHost.close(); await savesHost.close(); } };
|