Skip to content

Commit 3e402fb

Browse files
authored
Merge pull request #159 from Genymobile/dev/player-50-camera-widget
[Player-59] camera widget
2 parents 4c545c9 + e1f91a0 commit 3e402fb

28 files changed

Lines changed: 1378 additions & 15452 deletions

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v16
1+
v20

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ request. It's not mandatory at all, but feel free to open an issue to present yo
2424

2525
To start working on the Genymotion device web player, all you need if an HTML page to instanciate a player from your
2626
local copy of this repository.
27+
2728
Build the player in dev mode:
2829

2930
```sh

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ A Modern, WebRTC compatible, Web browser:
5151

5252
## 📦 Installation
5353

54-
### 📥 Install via NPM / Yarn
54+
### 📥 Install via NPM / Yarn
55+
56+
**Node.js 20 or later is required.**
5557

5658
Using yarn:
5759

doc/assets/ic_camera.svg

Lines changed: 1 addition & 1 deletion
Loading

package-lock.json

Lines changed: 0 additions & 15261 deletions
This file was deleted.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
],
99
"types": "dist/index.d.ts",
1010
"engines": {
11-
"node": ">=16"
11+
"node": ">=20"
1212
},
13+
1314
"scripts": {
1415
"test": "vitest run",
1516
"test:ui": "vitest --ui",
@@ -43,6 +44,7 @@
4344
"@babel/preset-env": "^7.18.6",
4445
"@fullhuman/postcss-purgecss": "5.0.0",
4546
"@vitest/ui": "^4.0.15",
47+
"@vitejs/plugin-basic-ssl": "^2.1.0",
4648
"autoprefixer": "10.4.14",
4749
"babel-eslint": "^10.1.0",
4850
"eslint": "^7.32.0",

src/DeviceRenderer.js

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ export default class DeviceRenderer {
6969
// Event callbacks
7070
this.callbacks = {};
7171

72+
// Plugins/Widgets registry
73+
this.widgets = [];
74+
7275
// Event listeners
7376
this.allListeners = [];
7477

@@ -77,10 +80,6 @@ export default class DeviceRenderer {
7780
this.signalingDataChannel = null;
7881
this.cameraSender = null;
7982
this.microphoneSender = null;
80-
this.sdpConstraints = {
81-
offerToReceiveAudio: true,
82-
offerToReceiveVideo: true,
83-
};
8483

8584
// last accessed x/y position
8685
this.x = 0;
@@ -435,7 +434,8 @@ export default class DeviceRenderer {
435434
}
436435
// creating SDP offer
437436
try {
438-
const description = await this.peerConnection.createOffer(this.sdpConstraints);
437+
const description = await this.peerConnection.createOffer();
438+
log.debug('Generated SDP Offer:', description.sdp);
439439
this.setLocalDescription(description);
440440
} catch (error) {
441441
this.onWebRTCConnectionError(error);
@@ -470,6 +470,7 @@ export default class DeviceRenderer {
470470

471471
const config = {
472472
iceServers: iceServers,
473+
bundlePolicy: 'max-compat',
473474
};
474475

475476
if (!this.peerConnection) {
@@ -488,6 +489,13 @@ export default class DeviceRenderer {
488489
this.useWebsocketAsDataChannel = true;
489490
}
490491

492+
/*
493+
* Add transceivers to receive audio and video (VM screen/audio)
494+
* This replaces the legacy offerToReceiveAudio/Video constraints
495+
*/
496+
this.peerConnection.addTransceiver('audio', {direction: 'recvonly'});
497+
this.peerConnection.addTransceiver('video', {direction: 'recvonly'});
498+
491499
this.peerConnection.onicecandidate = (event) => {
492500
if (typeof event.candidate === 'undefined') {
493501
// Nothing we can do
@@ -971,6 +979,24 @@ export default class DeviceRenderer {
971979
return;
972980
}
973981

982+
// Cleanup specific widget resources dynamically
983+
this.widgets.forEach((widget) => {
984+
if (widget && typeof widget.destroy === 'function') {
985+
widget.destroy();
986+
}
987+
});
988+
989+
if (this.store && this.store.destroy) {
990+
this.store.destroy();
991+
}
992+
993+
if (this.fileUploaderWorkerBlobSRC) {
994+
URL.revokeObjectURL(this.fileUploaderWorkerBlobSRC);
995+
this.fileUploaderWorkerBlobSRC = null;
996+
}
997+
998+
this.emit('destroyed');
999+
9741000
this.removeAllListeners();
9751001
this.disconnect();
9761002
this.peerConnectionStats?.destroy();

src/DeviceRendererFactory.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ const defaultOptions = {
7878
* Setup & create instances of the device renderer
7979
*/
8080
export default class DeviceRendererFactory {
81-
constructor() {
82-
this.instances = [];
83-
}
81+
constructor() {}
8482

8583
/**
8684
* Setup a device renderer instance in the given dom element, for the device instance identified by its instanceWebRTCUrl.
@@ -170,8 +168,6 @@ export default class DeviceRendererFactory {
170168
instance.toolbarManager = new ToolbarManager(instance);
171169
instance.tooltipManager = new TooltipManager(instance);
172170

173-
this.instances.push(instance);
174-
175171
this.loadPlugins(instance);
176172
this.loadToolbar(instance);
177173
instance.onWebRTCReady();
@@ -253,7 +249,8 @@ export default class DeviceRendererFactory {
253249
}
254250
// eslint-disable-next-line no-unused-expressions
255251
if (plugin.class) {
256-
new plugin.class(instance, ...args);
252+
const widget = new plugin.class(instance, ...args);
253+
instance.widgets.push(widget);
257254
}
258255
}
259256
});
Lines changed: 3 additions & 0 deletions
Loading

src/assets/images/ic_camera_mic.svg

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)