@flashphoner/websdk 2.0.236 → 2.0.238

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.
@@ -0,0 +1,30 @@
1
+ .fp-localVideo {
2
+ border: 1px double black;
3
+ width: 322px;
4
+ height: 242px;
5
+ text-align: center;
6
+ background: #c0c0c0;
7
+ margin: 10px auto;
8
+ }
9
+
10
+ .fp-previewVideo {
11
+ border: 1px double black;
12
+ width: 802px;
13
+ height: 402px;
14
+ text-align: center;
15
+ background: #c0c0c0;
16
+ margin: 10px auto;
17
+ }
18
+
19
+ .display {
20
+ width: 100%;
21
+ height: 100%;
22
+ display: inline-block;
23
+ }
24
+
25
+ .display > video {
26
+ width: 100%;
27
+ height: 100%;
28
+ }
29
+
30
+
@@ -0,0 +1,118 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <link rel="stylesheet" href="../../dependencies/bootstrap/css/bootstrap.css">
7
+ <link rel="stylesheet" href="../../dependencies/bootstrap/font-awesome/css/font-awesome.min.css">
8
+ <link rel="stylesheet" href="screen-camera-mixer.css">
9
+ <title>Screen Sharing with Camera</title>
10
+ <script type="text/javascript" src="../../../../flashphoner.js"></script>
11
+ <script type="text/javascript" src="../../dependencies/jquery/jquery-1.12.0.js"></script>
12
+ <script type="text/javascript" src="../../dependencies/js/utils.js"></script>
13
+
14
+ <script type="text/javascript" src="screen-camera-mixer.js"></script>
15
+ <!-- Bootstrap JS -->
16
+ <script src="../../dependencies/bootstrap/js/bootstrap.js"></script>
17
+ </head>
18
+ <body onload="init_page()">
19
+ <div class="container">
20
+ <div class="row">
21
+ <h2 class="text-center col-sm-9">Screen Sharing with Camera</h2>
22
+ </div>
23
+ <div id="notify" class="modal fade" role="dialog">
24
+ <div class="modal-dialog modal-lg">
25
+ <div class="modal-content">
26
+ <div class="modal-header">
27
+ <button type="button" class="close" data-dismiss="modal">&times;</button>
28
+ <h2 class="modal-title text-center text-danger">Warning!</h2>
29
+ </div>
30
+ <div class="modal-body text-center">
31
+ <h2 class="text-primary">Screen sharing works only in desktop browsers</h2>
32
+ </div>
33
+ <div class="modal-footer">
34
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ <div id="row">
40
+ <h2 id="notifyFlash" class="text-danger"></h2>
41
+ <div class="col-sm-10 text-center">
42
+ <div class="col-sm-6 text-center">
43
+ <div class="col-sm-12 text-center">
44
+ <div class="col-sm-4">
45
+ <div class="form-group" id="fpsForm">
46
+ <span class="text-muted">FPS</span>
47
+ <input type="text" class="form-control" id="fps" value="15"/>
48
+ </div>
49
+ </div>
50
+ <div class="col-sm-4">
51
+ <div class="form-group" id="widthForm">
52
+ <span class="text-muted">Width</span>
53
+ <input type="text" class="form-control" id="width" value="640"/>
54
+ </div>
55
+ </div>
56
+ <div class="col-sm-4">
57
+ <div class="form-group" id="heightForm">
58
+ <span class="text-muted">Height</span>
59
+ <input type="text" class="form-control" id="height" value="480"/>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ <div class="col-sm-12 text-center">
64
+ <div class="col-sm-5">
65
+ <div class="form-group" id="mixer">
66
+ <span class="text-muted">Add to Mixer?</span>
67
+ <input type="checkbox" class="checkbox" style="margin: 10px auto" id="useMixer"/>
68
+ </div>
69
+ </div>
70
+ <div class="col-sm-5">
71
+ <div class="form-group" id="mixerInput">
72
+ <span class="text-muted">Mixer</span>
73
+ <input type="text" class="form-control" id="mixerName" placeholder="Mixer name"/>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ <div class="fp-localVideo" style="margin-top: 140px">
78
+ <div id="localVideoScreen" class="display"></div>
79
+ </div>
80
+ <div class="text-center text-muted">My Screen</div>
81
+ <div class="row row-space">
82
+ <div id="screenName"></div>
83
+ <div id="screenStatus"></div>
84
+ <div id="screenInfo"></div>
85
+ </div>
86
+ </div>
87
+ <div class="col-sm-6 text-center">
88
+ <div class="fp-localVideo" style="margin-top: 140px">
89
+ <div id="localVideoCamera" class="display"></div>
90
+ </div>
91
+ <div class="text-center text-muted">My Camera</div>
92
+ <div class="row row-space">
93
+ <div id="cameraName"></div>
94
+ <div id="cameraStatus"></div>
95
+ <div id="cameraInfo"></div>
96
+ </div>
97
+ </div>
98
+ <div class="row row-space text-center" style="margin-top: 20px">
99
+ <!--<div class="col-sm-10 text-center">-->
100
+ <div class="col-sm-7">
101
+ <div class="form-group" id="urlForm">
102
+ <input type="text" class="form-control" id="url" placeholder="Enter url with stream name"/>
103
+ </div>
104
+ </div>
105
+ <div class="col-sm-2 text-left">
106
+ <button id="connectBtn" type="button" class="btn btn-default">Connect</button>
107
+ </div>
108
+ <div class="col-sm-2 text-left">
109
+ <button id="publishBtn" type="button" class="btn btn-default">Start</button>
110
+ </div>
111
+ <!--</div>-->
112
+ </div>
113
+ </div>
114
+
115
+ </div>
116
+ </div>
117
+ </body>
118
+ </html>
@@ -0,0 +1,265 @@
1
+ const SESSION_STATUS = Flashphoner.constants.SESSION_STATUS;
2
+ const STREAM_STATUS = Flashphoner.constants.STREAM_STATUS;
3
+ const Browser = Flashphoner.Browser;
4
+ let localVideoScreen;
5
+ let localVideoCamera;
6
+
7
+ const init_page = function() {
8
+ //init api
9
+ try {
10
+ Flashphoner.init();
11
+ } catch(e) {
12
+ $("#notifyFlash").text("Your browser doesn't support WebRTC technology needed for this example");
13
+ return;
14
+ }
15
+
16
+ if (Browser.isAndroid() && Browser.isiOS()) {
17
+ $("#notify").modal('show');
18
+ return false;
19
+ }
20
+
21
+ localVideoScreen = document.getElementById("localVideoScreen");
22
+ localVideoCamera = document.getElementById("localVideoCamera");
23
+ $("#url").val(setURL() + "/" + createUUID(8));
24
+ $("#mixerName").val("mixer");
25
+ onDisconnected();
26
+
27
+ }
28
+
29
+ const isSafariMacOS = function() {
30
+ return Browser.isSafari() && !Browser.isAndroid() && !Browser.isiOS();
31
+ }
32
+
33
+ const setConnectButton = function(action, session) {
34
+ $("#connectBtn").text(action).off('click').click(function(){
35
+ if (validateForm()) {
36
+ muteInputs();
37
+ $(this).prop('disabled', true);
38
+ if (action === "Connect") {
39
+ connect();
40
+ } else if (action === "Disconnect") {
41
+ session.disconnect();
42
+ }
43
+ }
44
+ }).prop('disabled', false);
45
+ }
46
+
47
+ const setPublishButton = function(action, session, cameraStream) {
48
+ $("#publishBtn").text(action).off('click').click(function(){
49
+ if (action == "Start") {
50
+ startStreaming(session);
51
+ } else if (action === "Stop") {
52
+ $(this).prop('disabled', true);
53
+ cameraStream.stop();
54
+ }
55
+ }).prop('disabled', false);
56
+ }
57
+
58
+ const onStarted = function(cameraStream) {
59
+ setPublishButton("Stop", null, cameraStream);
60
+ $("#connectBtn").prop('disabled', false);
61
+ }
62
+
63
+ const onStopped = function(session) {
64
+ setPublishButton("Start", session, null);
65
+ $("#connectBtn").prop('disabled', false);
66
+ }
67
+
68
+ const onConnected = function(session) {
69
+ setPublishButton("Start", session, null);
70
+ setConnectButton("Disconnect", session);
71
+ }
72
+
73
+ const onDisconnected = function() {
74
+ unmuteInputs();
75
+ $("#publishBtn").prop('disabled', true);
76
+ setConnectButton("Connect", null);
77
+ }
78
+
79
+ const connect = function() {
80
+ //check if we already have session
81
+ let url = field("url");
82
+ //check if we already have session
83
+ if (Flashphoner.getSessions().length > 0) {
84
+ let session = Flashphoner.getSessions()[0];
85
+ if (session.getServerUrl() == url) {
86
+ return;
87
+ } else {
88
+ //remove session DISCONNECTED and FAILED callbacks
89
+ session.on(SESSION_STATUS.DISCONNECTED, function(){});
90
+ session.on(SESSION_STATUS.FAILED, function(){});
91
+ session.disconnect();
92
+ }
93
+ }
94
+
95
+ console.log("Create new session with url " + url);
96
+ Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, function(session){
97
+ //session connected, start streaming
98
+ setStatus("screen", SESSION_STATUS.ESTABLISHED);
99
+ setStatus("camera", SESSION_STATUS.ESTABLISHED);
100
+ onConnected(session);
101
+ }).on(SESSION_STATUS.DISCONNECTED, function(){
102
+ setStatus("screen", SESSION_STATUS.DISCONNECTED);
103
+ setStatus("camera", SESSION_STATUS.DISCONNECTED);
104
+ onDisconnected();
105
+ }).on(SESSION_STATUS.FAILED, function(){
106
+ setStatus("screen", SESSION_STATUS.FAILED);
107
+ setStatus("camera", SESSION_STATUS.DISCONNECTED);
108
+ onDisconnected();
109
+ });
110
+
111
+ }
112
+
113
+ const startStreaming = function(session) {
114
+ if (validateForm()) {
115
+ muteInputs();
116
+ $("publishBtn").prop('disabled', true);
117
+ startStreamingScreen(session);
118
+ }
119
+ }
120
+
121
+ const startStreamingScreen = function(session) {
122
+ let streamName = getStreamName("screen", field("url"));
123
+ let constraints = {
124
+ video: {
125
+ width: parseInt($('#width').val()),
126
+ height: parseInt($('#height').val()),
127
+ frameRate: parseInt($('#fps').val()),
128
+ type: "screen",
129
+ withoutExtension: true
130
+ }
131
+ };
132
+ if (Browser.isFirefox()) {
133
+ constraints.video.mediaSource = "screen";
134
+ }
135
+ let options = {
136
+ name: streamName,
137
+ display: localVideoScreen,
138
+ constraints: constraints
139
+ }
140
+ if (isSafariMacOS()) {
141
+ options.disableConstraintsNormalization = true;
142
+ }
143
+ session.createStream(options).on(STREAM_STATUS.PUBLISHING, function(screenStream) {
144
+ /*
145
+ * User can stop sharing screen capture using Chrome "stop" button.
146
+ * Catch onended video track event and stop publishing.
147
+ */
148
+ document.getElementById(screenStream.id()).srcObject.getVideoTracks()[0].onended = function (e) {
149
+ screenStream.stop();
150
+ };
151
+ document.getElementById(screenStream.id()).addEventListener('resize', function(event){
152
+ resizeVideo(event.target);
153
+ });
154
+ setStatus("screen", STREAM_STATUS.PUBLISHING, screenStream);
155
+ startStreamingCamera(session, screenStream);
156
+ }).on(STREAM_STATUS.UNPUBLISHED, function() {
157
+ setStatus("screen", STREAM_STATUS.UNPUBLISHED);
158
+ //enable start button
159
+ onStopped(session);
160
+ }).on(STREAM_STATUS.FAILED, function(stream) {
161
+ setStatus("screen", STREAM_STATUS.FAILED, stream);
162
+ //enable start button
163
+ onStopped(session);
164
+ }).publish();
165
+ }
166
+
167
+ const startStreamingCamera = function(session, screenStream) {
168
+ let streamName = getStreamName("camera", field("url"));
169
+ let options = {
170
+ name: streamName,
171
+ display: localVideoCamera
172
+ }
173
+ session.createStream(options).on(STREAM_STATUS.PUBLISHING, function(cameraStream) {
174
+ document.getElementById(cameraStream.id()).addEventListener('resize', function(event){
175
+ resizeVideo(event.target);
176
+ });
177
+ setStatus("camera", STREAM_STATUS.PUBLISHING, cameraStream);
178
+ onStarted(cameraStream);
179
+ }).on(STREAM_STATUS.UNPUBLISHED, function() {
180
+ setStatus("camera", STREAM_STATUS.UNPUBLISHED);
181
+ screenStream.stop();
182
+ }).on(STREAM_STATUS.FAILED, function(stream) {
183
+ setStatus("camera", STREAM_STATUS.FAILED, stream);
184
+ if (screenStream.status() == STREAM_STATUS.PUBLISHING) {
185
+ setStatus(STREAM_STATUS.FAILED, stream);
186
+ screenStream.stop();
187
+ }
188
+ }).publish();
189
+ }
190
+
191
+ //show connection or local stream status
192
+ const setStatus = function(type, status, stream) {
193
+ let nameField = $("#"+type+"Name");
194
+ let statusField = $("#"+type+"Status");
195
+ let infoField = $("#"+type+"Info");
196
+ if (stream) {
197
+ nameField.text(stream.name);
198
+ } else {
199
+ nameField.text("");
200
+ }
201
+ statusField.text(status).removeClass();
202
+ if (status == "PUBLISHING" || status == "ESTABLISHED") {
203
+ statusField.attr("class","text-success");
204
+ } else if (status == "DISCONNECTED" || status == "UNPUBLISHED") {
205
+ statusField.attr("class","text-muted");
206
+ } else if (status == "FAILED") {
207
+ statusField.attr("class","text-danger");
208
+ if (stream) {
209
+ infoField.text(stream.getInfo()).attr("class","text-muted");
210
+ }
211
+ }
212
+ }
213
+
214
+ const muteInputs = function() {
215
+ $(":input").each(function() {
216
+ $(this).prop('disabled',true);
217
+ });
218
+ }
219
+
220
+ const unmuteInputs = function() {
221
+ $(":input").each(function() {
222
+ $(this).prop('disabled',false);
223
+ });
224
+ }
225
+
226
+ const validateForm = function() {
227
+ let valid = true;
228
+ $(':text').each(function(){
229
+ if (!$(this).val()) {
230
+ highlightInput($(this));
231
+ valid = false;
232
+ } else {
233
+ let numericFields = ['fps', 'width', 'height'];
234
+ if (numericFields.indexOf(this.id) != -1 && !(parseInt($(this).val()) > 0)) {
235
+ highlightInput($(this));
236
+ valid = false;
237
+ } else {
238
+ removeHighlight($(this));
239
+ }
240
+ }
241
+ });
242
+ return valid;
243
+ }
244
+
245
+
246
+ const highlightInput = function(input) {
247
+ input.closest('.form-group').addClass("has-error");
248
+ }
249
+ const removeHighlight = function(input) {
250
+ input.closest('.form-group').removeClass("has-error");
251
+ }
252
+
253
+ function getStreamName(type, url) {
254
+ let streamName = url.endsWith('/') === false ? url.split('/')[3] : "";
255
+ if (streamName) {
256
+ streamName += "-" + type;
257
+ if ($("#useMixer").prop('checked')) {
258
+ let mixerName = field("mixerName");
259
+ if (mixerName) {
260
+ streamName += "#" + mixerName;
261
+ }
262
+ }
263
+ }
264
+ return streamName;
265
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flashphoner/websdk",
3
- "version": "2.0.236",
3
+ "version": "2.0.238",
4
4
  "description": "Official Flashphoner WebCallServer WebSDK package",
5
5
  "main": "./src/flashphoner-core.js",
6
6
  "types": "./src/flashphoner-core.d.ts",