evmux-app-framework 0.0.53 → 0.0.55

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": "evmux-app-framework",
3
- "version": "0.0.53",
3
+ "version": "0.0.55",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -35,7 +35,9 @@ export const availableRequests = {
35
35
  displayRichTextEditor: "displayRichTextEditor",
36
36
  displayToast: "displayToast",
37
37
  isSudioMode: "isSudioMode",
38
- getStudioParams: "getStudioParams"
38
+ getStudioParams: "getStudioParams",
39
+ getSoundRtc: "getSoundRtc",
40
+ signal: "signal",
39
41
 
40
42
 
41
43
  }
@@ -135,6 +137,14 @@ let createEventResultObject = (requestName, eventName, result) => {
135
137
  })
136
138
 
137
139
  }
140
+
141
+ signalApp(userAppInstanceId, data){
142
+ let theApp = this._userAppInstances[userAppInstanceId]
143
+ if(theApp && theApp.events[availableEvents.signalingEvent]){
144
+ let eventObj = createEventResultObject("EvEvent", availableEvents.signalingEvent, data)
145
+ this._sendPostMessageToUsrAppInstancesComponents(userAppInstanceId, eventObj, null)
146
+ }
147
+ }
138
148
 
139
149
  async onPostMessage(evt) {
140
150
  let requestObj = {};
@@ -7,7 +7,7 @@ import {availableRequests} from './AppsObserver'
7
7
 
8
8
  canHandleRequest(requestObj)
9
9
  {
10
- const supportedRequests = [availableRequests.getStudioParams];
10
+ const supportedRequests = [availableRequests.getStudioParams, availableRequests.getSoundRtc, availableRequests.signal];
11
11
  return supportedRequests.includes(requestObj.request);
12
12
  }
13
13
 
@@ -17,4 +17,13 @@ import {availableRequests} from './AppsObserver'
17
17
  antiScaleValue2: 1.0,
18
18
  }
19
19
  }
20
+
21
+ async signal(requestObj) {
22
+ return null
23
+ }
24
+
25
+
26
+ async getSoundRtc(requestObj) {
27
+ return "webrtc-mock-channel"
28
+ }
20
29
  }
@@ -20,7 +20,8 @@ export const availableEvents = {
20
20
  doubleClickOnWidget: "doubleClickOnWidget",
21
21
  widgetOnFocus: "widgetGotFocus",
22
22
  widgetOnBlur: "widgetOnBlur",
23
- studioParamsUpdated: "studioParamsUpdated",
23
+ studioParamsUpdated: "studioParamsUpdated",
24
+ signalingEvent: "signalingEvent",
24
25
  }
25
26
 
26
27
  export const layerTypes = {
@@ -20,4 +20,30 @@ export default class EvmuxAppsApiStudio {
20
20
  }
21
21
 
22
22
 
23
+ async signal(data){
24
+ let reqObj = {
25
+ request: availableRequests.signal,
26
+ userAppInstanceId: this.evmuxAppsApi._userAppInstanceId,
27
+ componentId: this.evmuxAppsApi._componentId,
28
+ data
29
+ }
30
+ return this.evmuxAppsApi._postMessageManager.sendRequestAsync(reqObj);
31
+ }
32
+
33
+ async getSoundRtc(userId, userType, preferedCodecs){ // userType: 'editor' | 'speaker' | 'guest'
34
+ let reqObj = {
35
+ request: availableRequests.getSoundRtc,
36
+ userAppInstanceId: this.evmuxAppsApi._userAppInstanceId,
37
+ componentId: this.evmuxAppsApi._componentId,
38
+ data: {
39
+ userId,
40
+ userType,
41
+ preferedCodecs
42
+ }
43
+ }
44
+ let res = this.evmuxAppsApi._postMessageManager.sendRequestAsync(reqObj);
45
+ return res
46
+ }
47
+
48
+
23
49
  }
@@ -0,0 +1,163 @@
1
+
2
+
3
+
4
+ export class EvWebrtc{
5
+
6
+ constructor(component, channelName = 'webrtc', codecPreferences = null, postSignaligMessageFunc = null, endedCallback = null) {
7
+
8
+ this.component = component
9
+ this.channelName = channelName
10
+ this.codecPreferences = codecPreferences
11
+ this.postSignaligMessageFunc = postSignaligMessageFunc
12
+ this.pc = null
13
+ this.endedCallback = endedCallback
14
+ this.localStream = null
15
+ this.remoteStream = null
16
+ this.signaling = new BroadcastChannel(this.channelName);
17
+ this.signaling.onmessage = (e) => this.signalingMessageHandler(e);
18
+ }
19
+
20
+ postSignaligMessage(message){
21
+ message.channelName = this.channelName
22
+ if(this.postSignaligMessageFunc){
23
+ this.postSignaligMessageFunc(message)
24
+ }else{
25
+ this.signaling.postMessage(message);
26
+ }
27
+ }
28
+
29
+ signalingMessageHandler(e) {
30
+ if (!this.localStream) {
31
+ console.log('not ready yet', this.component);
32
+ return;
33
+ }
34
+ switch (e.type) {
35
+ case 'offer':
36
+ this.handleOffer(e);
37
+ break;
38
+ case 'answer':
39
+ this.handleAnswer(e);
40
+ break;
41
+ case 'candidate':
42
+ this.handleCandidate(e);
43
+ break;
44
+ case 'ready':
45
+ // A second tab joined. This tab will initiate a call unless in a call already.
46
+ if (this.pc) {
47
+ console.log('already in call, ignoring');
48
+ return;
49
+ }
50
+ this.makeCall();
51
+ break;
52
+ case 'bye':
53
+ if (this.pc) {
54
+ this.hangup();
55
+ }
56
+ if(this.endedCallback){
57
+ this.endedCallback()
58
+ }
59
+ break;
60
+ default:
61
+ console.log('unhandled', e);
62
+ break;
63
+ }
64
+ }
65
+
66
+ onconnectionstatechange(e){
67
+ console.log('connection state change', e);
68
+ }
69
+
70
+ oniceconnectionstatechange(e){
71
+ console.log('ice connection state change', e);
72
+ }
73
+
74
+ async hangup() {
75
+ if (this.pc) {
76
+ this.pc.close();
77
+ this.pc = null;
78
+ this.postSignaligMessage({type: 'bye'});
79
+ }
80
+ // this.localStream.getTracks().forEach(track => track.stop());
81
+ // this.localStream = null;
82
+ };
83
+
84
+ ready(){
85
+ this.postSignaligMessage({type: 'ready'});
86
+ }
87
+
88
+
89
+ createPeerConnection() {
90
+ this.pc = new RTCPeerConnection();
91
+ this.pc.onconnectionstatechange = e => this.onconnectionstatechange(e);
92
+ this.pc.oniceconnectionstatechange = e => this.oniceconnectionstatechange(e);
93
+ this.pc.onicecandidate = e => {
94
+ console.log('onicecandidate', this.component, e);
95
+ const message = {
96
+ type: 'candidate',
97
+ candidate: null,
98
+ };
99
+ if (e.candidate) {
100
+ message.candidate = e.candidate.candidate;
101
+ message.sdpMid = e.candidate.sdpMid;
102
+ message.sdpMLineIndex = e.candidate.sdpMLineIndex;
103
+ }
104
+ this.postSignaligMessage(message);
105
+ };
106
+ this.pc.ontrack = e => this.remoteStream = e.streams[0];
107
+ this.localStream.getTracks().forEach(track => this.pc.addTrack(track, this.localStream));
108
+ }
109
+
110
+ async makeCall() {
111
+ console.log('make call', this.component);
112
+ await this.createPeerConnection();
113
+ let transceivers = this.pc.getTransceivers()
114
+ if(this.codecPreferences){
115
+ transceivers.forEach(t => {
116
+ t.setCodecPreferences(this.codecPreferences)
117
+ })
118
+
119
+ }
120
+
121
+
122
+ const offer = await this.pc.createOffer();
123
+ this.postSignaligMessage({type: 'offer', sdp: offer.sdp});
124
+ await this.pc.setLocalDescription(offer);
125
+ }
126
+
127
+ async handleOffer(offer) {
128
+ console.log('handle offer', this.component);
129
+ if (this.pc) {
130
+ console.error('existing peerconnection');
131
+ return;
132
+ }
133
+ await this.createPeerConnection();
134
+ await this.pc.setRemoteDescription(offer);
135
+
136
+ const answer = await this.pc.createAnswer();
137
+ this.postSignaligMessage({type: 'answer', sdp: answer.sdp});
138
+ await this.pc.setLocalDescription(answer);
139
+ }
140
+
141
+ async handleAnswer(answer) {
142
+ console.log('handle answer', this.component);
143
+ if (!this.pc) {
144
+ console.error('no peerconnection');
145
+ return;
146
+ }
147
+ await this.pc.setRemoteDescription(answer);
148
+ }
149
+
150
+ async handleCandidate(candidate) {
151
+ console.log('handle candidate', this.component);
152
+ if (!this.pc) {
153
+ console.error('no peerconnection');
154
+ return;
155
+ }
156
+ if (!candidate.candidate) {
157
+ await this.pc.addIceCandidate(null);
158
+ } else {
159
+ await this.pc.addIceCandidate(candidate);
160
+ }
161
+ }
162
+
163
+ }