Commit 7a216f4c by Christoph

V0.984 rc.

* Cleanup callapp for easier use * Support for async init to have video devices available from the first frame * better work with recent Chrome changes and if loaded via http / file: url’s (mediaDevices null) * Will fail now during init some WebRTC features aren’t available to avoid cryptic error messages during runtime * Added GetBufferedAmount
parent 062d45ee
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<input type="checkbox" name="audio" class="callapp_send_audio" checked autocomplete="off"> Audio <input type="checkbox" name="audio" class="callapp_send_audio" checked autocomplete="off"> Audio
<input type="checkbox" name="video" class="callapp_send_video" checked autocomplete="off"> Video <input type="checkbox" name="video" class="callapp_send_video" checked autocomplete="off"> Video
<input type= "text" class="callapp_address" autocomplete="off"> <input type= "text" class="callapp_address" autocomplete="off">
<button class="callapp_button"> Start / Stop </button> <button class="callapp_button"> Join </button>
<div class="callapp_local_video">local video</div> <div class="callapp_local_video">local video</div>
<div class="callapp_remote_video">remote video</div> <div class="callapp_remote_video">remote video</div>
</div> </div>
......
...@@ -9,9 +9,8 @@ ...@@ -9,9 +9,8 @@
<button onclick="apps.BrowserMediaNetwork_frameaccess()">BrowserMediaNetwork_frameaccess</button><br> <button onclick="apps.BrowserMediaNetwork_frameaccess()">BrowserMediaNetwork_frameaccess</button><br>
<button onclick="apps.WebsocketNetwork_sharedaddress()">WebsocketNetwork_sharedaddress</button><br> <button onclick="apps.WebsocketNetwork_sharedaddress()">WebsocketNetwork_sharedaddress</button><br>
<button onclick="apps.WebsocketNetwork_test1()">WebsocketNetwork_test1</button><br> <button onclick="apps.WebsocketNetwork_test1()">WebsocketNetwork_test1</button><br>
<button onclick="apps.CAPIWebRtcNetwork_testapp()">CAPIWebRtcNetwork_testapp</button><br> <button onclick="apps.CAPI_WebRtcNetwork_testapp()">CAPI_WebRtcNetwork_testapp</button><br>
<button onclick="apps.CAPIMediaNetwork_testapp()">CAPIMediaNetwork_testapp</button><br> <button onclick="apps.CAPI_MediaNetwork_testapp()">CAPI_MediaNetwork_testapp</button><br>
<button onclick="apps.CAPIMediaStreamAPI()">CAPIMediaStreamAPI</button><br>
</head> </head>
<body> <body>
<script> <script>
......
{ {
"name": "awrtc_browser", "name": "awrtc_browser",
"version": "0.98.3", "version": "0.98.4",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
...@@ -1389,7 +1389,8 @@ ...@@ -1389,7 +1389,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
...@@ -1410,12 +1411,14 @@ ...@@ -1410,12 +1411,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
...@@ -1430,17 +1433,20 @@ ...@@ -1430,17 +1433,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
...@@ -1557,7 +1563,8 @@ ...@@ -1557,7 +1563,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
...@@ -1569,6 +1576,7 @@ ...@@ -1569,6 +1576,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
...@@ -1583,6 +1591,7 @@ ...@@ -1583,6 +1591,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
...@@ -1590,12 +1599,14 @@ ...@@ -1590,12 +1599,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.2.4", "version": "2.2.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1", "safe-buffer": "^5.1.1",
"yallist": "^3.0.0" "yallist": "^3.0.0"
...@@ -1614,6 +1625,7 @@ ...@@ -1614,6 +1625,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
...@@ -1694,7 +1706,8 @@ ...@@ -1694,7 +1706,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
...@@ -1706,6 +1719,7 @@ ...@@ -1706,6 +1719,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
...@@ -1791,7 +1805,8 @@ ...@@ -1791,7 +1805,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
...@@ -1827,6 +1842,7 @@ ...@@ -1827,6 +1842,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
...@@ -1846,6 +1862,7 @@ ...@@ -1846,6 +1862,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
...@@ -1889,12 +1906,14 @@ ...@@ -1889,12 +1906,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
......
{ {
"name": "awrtc_browser", "name": "awrtc_browser",
"version": "0.98.3", "version": "0.98.4",
"description": "", "description": "",
"author": "because-why-not.com Limited", "author": "because-why-not.com Limited",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
......
...@@ -125,7 +125,7 @@ interface IRemoteVideoDict { ...@@ -125,7 +125,7 @@ interface IRemoteVideoDict {
class MinimalCall class MinimalCall
{ {
//just a number we give each local call to //just a number we give each local call to
//identify the output of each indivudal call //identify the output of each individual call
mId:number = -1; mId:number = -1;
mCall: awrtc.BrowserWebRtcCall = null; mCall: awrtc.BrowserWebRtcCall = null;
mLocalVideo: HTMLVideoElement = null; mLocalVideo: HTMLVideoElement = null;
...@@ -168,11 +168,12 @@ class MinimalCall ...@@ -168,11 +168,12 @@ class MinimalCall
private OnCallEvent(sender: any, args: awrtc.CallEventArgs) private OnCallEvent(sender: any, args: awrtc.CallEventArgs)
{ {
if (args.Type == awrtc.CallEventType.ConfigurationComplete) { if (args.Type == awrtc.CallEventType.ConfigurationComplete) {
console.log("configuration complete"); console.log("configuration complete");
this.mCall.Listen(this.mAddress); this.mCall.Listen(this.mAddress);
} else if (args.Type == awrtc.CallEventType.FrameUpdate) { }/* Old system. not used anymore
else if (args.Type == awrtc.CallEventType.FrameUpdate) {
let frameUpdateArgs = args as awrtc.FrameUpdateEventArgs; let frameUpdateArgs = args as awrtc.FrameUpdateEventArgs;
if (this.mLocalVideo == null && frameUpdateArgs.ConnectionId == awrtc.ConnectionId.INVALID) { if (this.mLocalVideo == null && frameUpdateArgs.ConnectionId == awrtc.ConnectionId.INVALID) {
...@@ -190,7 +191,28 @@ class MinimalCall ...@@ -190,7 +191,28 @@ class MinimalCall
this.mRemoteVideo[frameUpdateArgs.ConnectionId.id] = lazyFrame.FrameGenerator.VideoElement; this.mRemoteVideo[frameUpdateArgs.ConnectionId.id] = lazyFrame.FrameGenerator.VideoElement;
this.mDiv.appendChild(this.mRemoteVideo[frameUpdateArgs.ConnectionId.id]); this.mDiv.appendChild(this.mRemoteVideo[frameUpdateArgs.ConnectionId.id]);
} }
} else if (args.Type == awrtc.CallEventType.ListeningFailed) { }*/
else if (args.Type == awrtc.CallEventType.MediaUpdate) {
let margs = args as awrtc.MediaUpdatedEventArgs;
if (this.mLocalVideo == null && margs.ConnectionId == awrtc.ConnectionId.INVALID) {
var videoElement = margs.VideoElement;
this.mLocalVideo = videoElement;
this.mDiv.innerHTML += "local video: " + "<br>";
this.mDiv.appendChild(videoElement);
console.log("local video added resolution:" + videoElement.videoWidth + videoElement.videoHeight + " fps: ??");
}
else if (margs.ConnectionId != awrtc.ConnectionId.INVALID && this.mRemoteVideo[margs.ConnectionId.id] == null) {
var videoElement = margs.VideoElement;
this.mRemoteVideo[margs.ConnectionId.id] = videoElement;
this.mDiv.innerHTML += "remote " + this.mId + "<br>";
this.mDiv.appendChild(videoElement);
console.log("remote video added resolution:" + videoElement.videoWidth + videoElement.videoHeight + " fps: ??");
}
}else if (args.Type == awrtc.CallEventType.ListeningFailed) {
if (this.mNetConfig.IsConference == false) { if (this.mNetConfig.IsConference == false) {
//in 1 to 1 calls there is a listener and a caller //in 1 to 1 calls there is a listener and a caller
...@@ -242,9 +264,11 @@ export function BrowserWebRtcCall_minimal() { ...@@ -242,9 +264,11 @@ export function BrowserWebRtcCall_minimal() {
let mediaConfigSender = new awrtc.MediaConfig(); let mediaConfigSender = new awrtc.MediaConfig();
mediaConfigSender.Video = true; mediaConfigSender.Video = true;
mediaConfigSender.Audio = true; mediaConfigSender.Audio = true;
mediaConfigSender.FrameUpdates = false;
let mediaConfigReceiver = new awrtc.MediaConfig(); let mediaConfigReceiver = new awrtc.MediaConfig();
mediaConfigReceiver.Video = false; mediaConfigReceiver.Video = false;
mediaConfigReceiver.Audio = false; mediaConfigReceiver.Audio = false;
mediaConfigReceiver.FrameUpdates = false;
//random key so we don't mistakenly connect //random key so we don't mistakenly connect
//to another user //to another user
......
...@@ -37,7 +37,7 @@ import { DeviceApi, DeviceInfo } from "../awrtc/index"; ...@@ -37,7 +37,7 @@ import { DeviceApi, DeviceInfo } from "../awrtc/index";
//testapp to run a full connection test using the CAPI //testapp to run a full connection test using the CAPI
//which is used by the unity WebGL plugin //which is used by the unity WebGL plugin
export function CAPIWebRtcNetwork_testapp() { export function CAPI_WebRtcNetwork_testapp() {
console.log("test1"); console.log("test1");
var testMessage = "test1234"; var testMessage = "test1234";
...@@ -46,26 +46,26 @@ export function CAPIWebRtcNetwork_testapp() { ...@@ -46,26 +46,26 @@ export function CAPIWebRtcNetwork_testapp() {
//var configuration = "{ \"signaling\" : { \"class\": \"WebsocketNetwork\", \"param\" : \"ws://localhost:12776\"}, \"iceServers\":[\"stun:stun.l.google.com:19302\"]}"; //var configuration = "{ \"signaling\" : { \"class\": \"WebsocketNetwork\", \"param\" : \"ws://localhost:12776\"}, \"iceServers\":[\"stun:stun.l.google.com:19302\"]}";
var configuration = "{ \"signaling\" : { \"class\": \"LocalNetwork\", \"param\" : null}, \"iceServers\":[{\"urls\": \"stun:stun.l.google.com:19302\"}]}"; var configuration = "{ \"signaling\" : { \"class\": \"LocalNetwork\", \"param\" : null}, \"iceServers\":[{\"urls\": \"stun:stun.l.google.com:19302\"}]}";
var srv = awrtc.CAPIWebRtcNetworkCreate(configuration); var srv = awrtc.CAPI_WebRtcNetwork_Create(configuration);
awrtc.CAPIWebRtcNetworkStartServer(srv, "Room1"); awrtc.CAPI_WebRtcNetwork_StartServer(srv, "Room1");
var clt = awrtc.CAPIWebRtcNetworkCreate(configuration); var clt = awrtc.CAPI_WebRtcNetwork_Create(configuration);
setInterval(() => { setInterval(() => {
awrtc.CAPIWebRtcNetworkUpdate(srv); awrtc.CAPI_WebRtcNetwork_Update(srv);
var evt = null; var evt = null;
while (evt = awrtc.CAPIWebRtcNetworkDequeue(srv)) { while (evt = awrtc.CAPI_WebRtcNetwork_Dequeue(srv)) {
console.log("server inc: " + evt.toString()); console.log("server inc: " + evt.toString());
if (evt.Type == awrtc.NetEventType.ServerInitialized) { if (evt.Type == awrtc.NetEventType.ServerInitialized) {
console.log("server started. Address " + evt.Info); console.log("server started. Address " + evt.Info);
awrtc.CAPIWebRtcNetworkConnect(clt, evt.Info); awrtc.CAPI_WebRtcNetwork_Connect(clt, evt.Info);
} else if (evt.Type == awrtc.NetEventType.ServerInitFailed) { } else if (evt.Type == awrtc.NetEventType.ServerInitFailed) {
console.error("server start failed"); console.error("server start failed");
...@@ -74,21 +74,21 @@ export function CAPIWebRtcNetwork_testapp() { ...@@ -74,21 +74,21 @@ export function CAPIWebRtcNetwork_testapp() {
} else if (evt.Type == awrtc.NetEventType.Disconnected) { } else if (evt.Type == awrtc.NetEventType.Disconnected) {
console.log("server peer disconnected"); console.log("server peer disconnected");
console.log("server shutdown"); console.log("server shutdown");
awrtc.CAPIWebRtcNetworkShutdown(srv); awrtc.CAPI_WebRtcNetwork_Shutdown(srv);
} else if (evt.Type == awrtc.NetEventType.ReliableMessageReceived) { } else if (evt.Type == awrtc.NetEventType.ReliableMessageReceived) {
//srv.SendData(evt.ConnectionId, evt.MessageData, true); //srv.SendData(evt.ConnectionId, evt.MessageData, true);
awrtc.CAPIWebRtcNetworkSendData(srv, evt.ConnectionId.id, evt.MessageData, true); awrtc.CAPI_WebRtcNetwork_SendData(srv, evt.ConnectionId.id, evt.MessageData, true);
} else if (evt.Type == awrtc.NetEventType.UnreliableMessageReceived) { } else if (evt.Type == awrtc.NetEventType.UnreliableMessageReceived) {
//srv.SendData(evt.ConnectionId, evt.MessageData, false); //srv.SendData(evt.ConnectionId, evt.MessageData, false);
awrtc.CAPIWebRtcNetworkSendData(srv, evt.ConnectionId.id, evt.MessageData, false); awrtc.CAPI_WebRtcNetwork_SendData(srv, evt.ConnectionId.id, evt.MessageData, false);
} }
} }
//srv.Flush(); //srv.Flush();
awrtc.CAPIWebRtcNetworkFlush(srv); awrtc.CAPI_WebRtcNetwork_Flush(srv);
//clt.Update(); //clt.Update();
awrtc.CAPIWebRtcNetworkUpdate(clt); awrtc.CAPI_WebRtcNetwork_Update(clt);
while (evt = awrtc.CAPIWebRtcNetworkDequeue(clt)) { while (evt = awrtc.CAPI_WebRtcNetwork_Dequeue(clt)) {
console.log("client inc: " + evt.toString()); console.log("client inc: " + evt.toString());
...@@ -97,7 +97,7 @@ export function CAPIWebRtcNetwork_testapp() { ...@@ -97,7 +97,7 @@ export function CAPIWebRtcNetwork_testapp() {
let buff = awrtc.Encoding.UTF16.GetBytes(testMessage); let buff = awrtc.Encoding.UTF16.GetBytes(testMessage);
//clt.SendData(evt.ConnectionId, buff, true); //clt.SendData(evt.ConnectionId, buff, true);
awrtc.CAPIWebRtcNetworkSendData(clt, evt.ConnectionId.id, buff, true); awrtc.CAPI_WebRtcNetwork_SendData(clt, evt.ConnectionId.id, buff, true);
} else if (evt.Type == awrtc.NetEventType.ReliableMessageReceived) { } else if (evt.Type == awrtc.NetEventType.ReliableMessageReceived) {
//check last message //check last message
...@@ -110,7 +110,7 @@ export function CAPIWebRtcNetwork_testapp() { ...@@ -110,7 +110,7 @@ export function CAPIWebRtcNetwork_testapp() {
let buff = awrtc.Encoding.UTF16.GetBytes(testMessage); let buff = awrtc.Encoding.UTF16.GetBytes(testMessage);
//clt.SendData(evt.ConnectionId, buff, false); //clt.SendData(evt.ConnectionId, buff, false);
awrtc.CAPIWebRtcNetworkSendData(clt, evt.ConnectionId.id, buff, false); awrtc.CAPI_WebRtcNetwork_SendData(clt, evt.ConnectionId.id, buff, false);
} else if (evt.Type == awrtc.NetEventType.UnreliableMessageReceived) { } else if (evt.Type == awrtc.NetEventType.UnreliableMessageReceived) {
let str = awrtc.Encoding.UTF16.GetString(evt.MessageData); let str = awrtc.Encoding.UTF16.GetString(evt.MessageData);
if (str != testMessage) { if (str != testMessage) {
...@@ -119,49 +119,49 @@ export function CAPIWebRtcNetwork_testapp() { ...@@ -119,49 +119,49 @@ export function CAPIWebRtcNetwork_testapp() {
console.log("client disconnecting"); console.log("client disconnecting");
//clt.Disconnect(evt.ConnectionId); //clt.Disconnect(evt.ConnectionId);
awrtc.CAPIWebRtcNetworkDisconnect(clt, evt.ConnectionId.id); awrtc.CAPI_WebRtcNetwork_Disconnect(clt, evt.ConnectionId.id);
console.log("client shutting down"); console.log("client shutting down");
//clt.Shutdown(); //clt.Shutdown();
awrtc.CAPIWebRtcNetworkShutdown(clt); awrtc.CAPI_WebRtcNetwork_Shutdown(clt);
} }
} }
//clt.Flush(); //clt.Flush();
awrtc.CAPIWebRtcNetworkFlush(clt); awrtc.CAPI_WebRtcNetwork_Flush(clt);
}, 100); }, 100);
} }
//for testing the media API used by the unity plugin //for testing the media API used by the unity plugin
export function CAPIMediaNetwork_testapp() export function CAPI_MediaNetwork_testapp()
{ {
awrtc.BrowserMediaStream.DEBUG_SHOW_ELEMENTS = true; awrtc.BrowserMediaStream.DEBUG_SHOW_ELEMENTS = true;
var signalingUrl : string = DefaultValues.Signaling; var signalingUrl : string = DefaultValues.Signaling;
let lIndex = awrtc.CAPIMediaNetwork_Create("{\"IceUrls\":[\"stun:stun.l.google.com:19302\"], \"SignalingUrl\":\"ws://because-why-not.com:12776\"}"); let lIndex = awrtc.CAPI_MediaNetwork_Create("{\"IceUrls\":[\"stun:stun.l.google.com:19302\"], \"SignalingUrl\":\"ws://because-why-not.com:12776\"}");
let configDone = false; let configDone = false;
awrtc.CAPIMediaNetwork_Configure(lIndex, true, true, 160, 120, 640, 480, 640, 480, -1, -1, -1); awrtc.CAPI_MediaNetwork_Configure(lIndex, true, true, 160, 120, 640, 480, 640, 480, -1, -1, -1);
console.log(awrtc.CAPIMediaNetwork_GetConfigurationState(lIndex)); console.log(awrtc.CAPI_MediaNetwork_GetConfigurationState(lIndex));
let startTime = new Date().getTime(); let startTime = new Date().getTime();
let mainLoop = function () { let mainLoop = function () {
awrtc.CAPIWebRtcNetworkUpdate(lIndex); awrtc.CAPI_WebRtcNetwork_Update(lIndex);
if (awrtc.CAPIMediaNetwork_GetConfigurationState(lIndex) == (awrtc.MediaConfigurationState.Successful as number) && configDone == false) { if (awrtc.CAPI_MediaNetwork_GetConfigurationState(lIndex) == (awrtc.MediaConfigurationState.Successful as number) && configDone == false) {
configDone = true; configDone = true;
console.log("configuration done"); console.log("configuration done");
} }
if (awrtc.CAPIMediaNetwork_GetConfigurationState(lIndex) == (awrtc.MediaConfigurationState.Failed as number)) { if (awrtc.CAPI_MediaNetwork_GetConfigurationState(lIndex) == (awrtc.MediaConfigurationState.Failed as number)) {
alert("configuration failed"); alert("configuration failed");
} }
if (configDone == false) if (configDone == false)
console.log(awrtc.CAPIMediaNetwork_GetConfigurationState(lIndex)); console.log(awrtc.CAPI_MediaNetwork_GetConfigurationState(lIndex));
if ((new Date().getTime() - startTime) < 15000) { if ((new Date().getTime() - startTime) < 15000) {
window.requestAnimationFrame(mainLoop); window.requestAnimationFrame(mainLoop);
} else { } else {
console.log("shutting down"); console.log("shutting down");
awrtc.CAPIWebRtcNetworkRelease(lIndex); awrtc.CAPI_WebRtcNetwork_Release(lIndex);
} }
} }
window.requestAnimationFrame(mainLoop); window.requestAnimationFrame(mainLoop);
...@@ -412,7 +412,7 @@ class FpsCounter ...@@ -412,7 +412,7 @@ class FpsCounter
} }
//Sends video data between two peers within the same browser window //Sends video data between two peers within the same browser window
//and accesses the resultung frame data directly //and accesses the resulting frame data directly
export function BrowserMediaNetwork_frameaccess() { export function BrowserMediaNetwork_frameaccess() {
......
...@@ -138,7 +138,7 @@ export class BrowserMediaNetwork extends WebRtcNetwork implements IMediaNetwork ...@@ -138,7 +138,7 @@ export class BrowserMediaNetwork extends WebRtcNetwork implements IMediaNetwork
//user requested specific device? get it now to properly add it to the //user requested specific device? get it now to properly add it to the
//constraints alter //constraints later
let deviceId:string = null; let deviceId:string = null;
if(config.Video && config.VideoDeviceName && config.VideoDeviceName !== "") if(config.Video && config.VideoDeviceName && config.VideoDeviceName !== "")
{ {
...@@ -184,30 +184,39 @@ export class BrowserMediaNetwork extends WebRtcNetwork implements IMediaNetwork ...@@ -184,30 +184,39 @@ export class BrowserMediaNetwork extends WebRtcNetwork implements IMediaNetwork
constraints.video = video; constraints.video = video;
SLog.L("calling GetUserMedia. Media constraints: " + JSON.stringify(constraints)); SLog.L("calling GetUserMedia. Media constraints: " + JSON.stringify(constraints));
let promise = navigator.mediaDevices.getUserMedia(constraints); if(navigator && navigator.mediaDevices)
promise.then((stream) => { //user gave permission {
let promise = navigator.mediaDevices.getUserMedia(constraints);
//totally unrelated -> user gave access to devices. use this promise.then((stream) => { //user gave permission
//to get the proper names for our DeviceApi
DeviceApi.Update(); //totally unrelated -> user gave access to devices. use this
//to get the proper names for our DeviceApi
//call worked -> setup a frame buffer that deals with the rest DeviceApi.Update();
this.mLocalStream = new BrowserMediaStream(stream as MediaStream);
this.mLocalStream.InternalStreamAdded = (stream)=>{ //call worked -> setup a frame buffer that deals with the rest
this.EnqueueMediaEvent(MediaEventType.StreamAdded, ConnectionId.INVALID, this.mLocalStream.VideoElement); this.mLocalStream = new BrowserMediaStream(stream as MediaStream);
}; this.mLocalStream.InternalStreamAdded = (stream)=>{
this.EnqueueMediaEvent(MediaEventType.StreamAdded, ConnectionId.INVALID, this.mLocalStream.VideoElement);
//unlike native version this one will happily play the local sound causing an echo };
//set to mute
this.mLocalStream.SetMute(true); //unlike native version this one will happily play the local sound causing an echo
this.OnConfigurationSuccess(); //set to mute
this.mLocalStream.SetMute(true);
}); this.OnConfigurationSuccess();
promise.catch((err)=> {
//failed due to an error or user didn't give permissions });
SLog.LE(err.name + ": " + err.message); promise.catch((err)=> {
this.OnConfigurationFailed(err.message); //failed due to an error or user didn't give permissions
}); SLog.LE(err.name + ": " + err.message);
this.OnConfigurationFailed(err.message);
});
}else{
//no access to media device -> fail
let error = "Configuration failed. navigator.mediaDevices is unedfined. The browser might not allow media access." +
"Is the page loaded via http or file URL? Some browsers only support https!";
SLog.LE(error);
this.OnConfigurationFailed(error);
}
} else { } else {
this.OnConfigurationSuccess(); this.OnConfigurationSuccess();
} }
......
...@@ -53,6 +53,17 @@ export class DeviceApi ...@@ -53,6 +53,17 @@ export class DeviceApi
return DeviceApi.sLastUpdate > 0; return DeviceApi.sLastUpdate > 0;
} }
private static sIsPending = false;
public static get IsPending(){
return DeviceApi.sIsPending;
}
private static sLastError:string = null;
private static get LastError()
{
return this.sLastError;
}
private static sDeviceInfo: { [id: string] : DeviceInfo; } = {}; private static sDeviceInfo: { [id: string] : DeviceInfo; } = {};
private static sVideoDeviceCounter = 1; private static sVideoDeviceCounter = 1;
...@@ -87,6 +98,7 @@ export class DeviceApi ...@@ -87,6 +98,7 @@ export class DeviceApi
private static InternalOnEnum = (devices:MediaDeviceInfo[])=> private static InternalOnEnum = (devices:MediaDeviceInfo[])=>
{ {
DeviceApi.sIsPending = false;
DeviceApi.sLastUpdate = new Date().getTime(); DeviceApi.sLastUpdate = new Date().getTime();
let newDeviceInfo: { [id: string] : DeviceInfo; } = {}; let newDeviceInfo: { [id: string] : DeviceInfo; } = {};
...@@ -141,7 +153,10 @@ export class DeviceApi ...@@ -141,7 +153,10 @@ export class DeviceApi
if(DeviceApi.sAccessStream) if(DeviceApi.sAccessStream)
{ {
DeviceApi.sAccessStream.stop(); var tracks = DeviceApi.sAccessStream.getTracks();
for (var i = 0; i < tracks.length; i++) {
tracks[i].stop();
}
DeviceApi.sAccessStream = null; DeviceApi.sAccessStream = null;
} }
DeviceApi.TriggerChangedEvent(); DeviceApi.TriggerChangedEvent();
...@@ -158,11 +173,21 @@ export class DeviceApi ...@@ -158,11 +173,21 @@ export class DeviceApi
DeviceApi.sDeviceInfo = {}; DeviceApi.sDeviceInfo = {};
DeviceApi.sVideoDeviceCounter = 1; DeviceApi.sVideoDeviceCounter = 1;
DeviceApi.sAccessStream = null; DeviceApi.sAccessStream = null;
DeviceApi.sLastError = null;
DeviceApi.sIsPending = false;
} }
private static InternalOnError = (err:DOMError)=> private static InternalOnErrorCatch = (err:DOMError)=>
{
let txt :string = err.toString();
DeviceApi.InternalOnErrorString(txt);
}
private static InternalOnErrorString = (err:string)=>
{ {
DeviceApi.sIsPending = false;
DeviceApi.sLastError = err;
SLog.LE(err); SLog.LE(err);
DeviceApi.TriggerChangedEvent();
} }
private static InternalOnStream = (stream:MediaStream)=> private static InternalOnStream = (stream:MediaStream)=>
...@@ -173,24 +198,48 @@ export class DeviceApi ...@@ -173,24 +198,48 @@ export class DeviceApi
/**Updates the device list based on the current /**Updates the device list based on the current
* access. Given devices numbers if the name isn't known. * access. Gives the devices numbers if the name isn't known.
*/ */
public static Update():void public static Update():void
{ {
navigator.mediaDevices.enumerateDevices() DeviceApi.sLastError = null;
.then(DeviceApi.InternalOnEnum) if(DeviceApi.IsApiAvailable())
.catch(DeviceApi.InternalOnError); {
DeviceApi.sIsPending = true;
navigator.mediaDevices.enumerateDevices()
.then(DeviceApi.InternalOnEnum)
.catch(DeviceApi.InternalOnErrorCatch);
}else{
DeviceApi.InternalOnErrorString("Can't access mediaDevices or enumerateDevices");
}
}
/**Checks if the API is available in the browser.
* false - browser doesn't support this API
* true - browser supports the API (might still refuse to give
* us access later on)
*/
public static IsApiAvailable():boolean
{
if(navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices)
return true;
return false;
} }
/**Asks the user for access first to get the full /**Asks the user for access first to get the full
* device names. * device names.
*/ */
public static RequestUpdate():void public static RequestUpdate():void
{ {
let constraints = {video:true}; DeviceApi.sLastError = null;
navigator.mediaDevices.getUserMedia(constraints) if(DeviceApi.IsApiAvailable())
.then(DeviceApi.InternalOnStream) {
.catch(DeviceApi.InternalOnError); DeviceApi.sIsPending = true;
let constraints = {video:true};
navigator.mediaDevices.getUserMedia(constraints)
.then(DeviceApi.InternalOnStream)
.catch(DeviceApi.InternalOnErrorCatch);
}else{
DeviceApi.InternalOnErrorString("Can't access mediaDevices or enumerateDevices");
}
} }
......
...@@ -127,7 +127,9 @@ export class MediaPeer extends WebRtcDataPeer ...@@ -127,7 +127,9 @@ export class MediaPeer extends WebRtcDataPeer
} }
else{ else{
for(let v of stream.getTracks()) for(let v of stream.getTracks())
{
this.mPeer.addTrack(v, stream); this.mPeer.addTrack(v, stream);
}
} }
} }
......
...@@ -196,27 +196,39 @@ export class SLog { ...@@ -196,27 +196,39 @@ export class SLog {
{ {
SLog.sLogLevel = level; SLog.sLogLevel = level;
} }
public static RequestLogLevel(level: SLogLevel)
{
if(level > SLog.sLogLevel)
SLog.sLogLevel = level;
}
public static L(msg: any): void { public static L(msg: any, tag?:string): void {
SLog.Log(msg); SLog.Log(msg, tag);
} }
public static LW(msg: any): void { public static LW(msg: any, tag?:string): void {
SLog.LogWarning(msg); SLog.LogWarning(msg, tag);
} }
public static LE(msg: any): void { public static LE(msg: any, tag?:string): void {
SLog.LogError(msg); SLog.LogError(msg, tag);
} }
public static Log(msg: any): void { public static Log(msg: any, tag?:string): void {
if(!tag)
tag = "";
if(SLog.sLogLevel >= SLogLevel.Info) if(SLog.sLogLevel >= SLogLevel.Info)
console.log(msg); console.log(msg, tag);
} }
public static LogWarning(msg: any): void { public static LogWarning(msg: any, tag?:string): void {
if(!tag)
tag = "";
if(SLog.sLogLevel >= SLogLevel.Warnings) if(SLog.sLogLevel >= SLogLevel.Warnings)
console.warn(msg); console.warn(msg, tag);
} }
public static LogError(msg: any) { public static LogError(msg: any, tag?:string) {
if(!tag)
tag = "";
if(SLog.sLogLevel >= SLogLevel.Errors) if(SLog.sLogLevel >= SLogLevel.Errors)
console.error(msg); console.error(msg, tag);
} }
} }
\ No newline at end of file
...@@ -49,7 +49,23 @@ export enum NetEventType { ...@@ -49,7 +49,23 @@ export enum NetEventType {
Disconnected = 8,//a connection was disconnected Disconnected = 8,//a connection was disconnected
FatalError = 100, //not yet used FatalError = 100, //not yet used
Warning = 101,//not yet used Warning = 101,//not yet used
Log = 102 //not yet used Log = 102, //not yet used
/// <summary>
/// This value and higher are reserved for other uses.
/// Should never get to the user and should be filtered out.
/// </summary>
ReservedStart = 200,
/// <summary>
/// Reserved.
/// Used by protocols that forward NetworkEvents
/// </summary>
MetaVersion = 201,
/// <summary>
/// Reserved.
/// Used by protocols that forward NetworkEvents.
/// </summary>
MetaHeartbeat = 202
} }
export enum NetEventDataType { export enum NetEventDataType {
Null = 0, Null = 0,
...@@ -330,6 +346,7 @@ export interface IBasicNetwork extends INetwork { ...@@ -330,6 +346,7 @@ export interface IBasicNetwork extends INetwork {
Connect(address: string): ConnectionId; Connect(address: string): ConnectionId;
} }
export interface IWebRtcNetwork extends IBasicNetwork { export interface IWebRtcNetwork extends IBasicNetwork {
GetBufferedAmount(id: ConnectionId, reliable:boolean): number;
} }
//export {NetEventType, NetworkEvent, ConnectionId, INetwork, IBasicNetwork}; //export {NetEventType, NetworkEvent, ConnectionId, INetwork, IBasicNetwork};
...@@ -151,8 +151,18 @@ export class WebRtcNetwork implements IBasicNetwork { ...@@ -151,8 +151,18 @@ export class WebRtcNetwork implements IBasicNetwork {
SLog.LogWarning("unknown connection id"); SLog.LogWarning("unknown connection id");
return false; return false;
} }
}
public GetBufferedAmount(id: ConnectionId, reliable: boolean): number {
let peer = this.mIdToConnection[id.id];
if (peer) {
return peer.GetBufferedAmount(reliable);
} else {
SLog.LogWarning("unknown connection id");
return -1;
}
} }
public Disconnect(id: ConnectionId): void { public Disconnect(id: ConnectionId): void {
let peer = this.mIdToConnection[id.id]; let peer = this.mIdToConnection[id.id];
......
...@@ -551,6 +551,27 @@ export class WebRtcDataPeer extends AWebRtcPeer { ...@@ -551,6 +551,27 @@ export class WebRtcDataPeer extends AWebRtcPeer {
} }
return sentSuccessfully; return sentSuccessfully;
} }
public GetBufferedAmount(reliable: boolean): number {
let result = -1;
try {
if (reliable) {
if (this.mReliableDataChannel.readyState === "open")
{
result = this.mReliableDataChannel.bufferedAmount;
}
}
else {
if (this.mUnreliableDataChannel.readyState === "open")
{
result = this.mUnreliableDataChannel.bufferedAmount;
}
}
} catch (e) {
SLog.LogError("Exception while trying to access GetBufferedAmount: " + e);
}
return result;
}
public DequeueEvent(/*out*/ ev: Output<NetworkEvent>): boolean { public DequeueEvent(/*out*/ ev: Output<NetworkEvent>): boolean {
//lock(mEvents) //lock(mEvents)
......
...@@ -45,10 +45,13 @@ export enum WebsocketServerStatus { ...@@ -45,10 +45,13 @@ export enum WebsocketServerStatus {
ShuttingDown ShuttingDown
} }
//TODO: handle errors if the socket connection failed //TODO: handle errors if the socket connection failed
//+ send back failed events for connected / serverstart events that are buffered //+ send back failed events for connected / serverstart events that are buffered
export class WebsocketNetwork implements IBasicNetwork { export class WebsocketNetwork implements IBasicNetwork {
public static readonly LOGTAG = "WebsocketNetwork";
//websocket. //websocket.
private mSocket: WebSocket; private mSocket: WebSocket;
...@@ -73,13 +76,40 @@ export class WebsocketNetwork implements IBasicNetwork { ...@@ -73,13 +76,40 @@ export class WebsocketNetwork implements IBasicNetwork {
//next free connection id //next free connection id
private mNextOutgoingConnectionId = new ConnectionId(1); private mNextOutgoingConnectionId = new ConnectionId(1);
/// <summary>
/// Version of the protocol implemented here
/// </summary>
public static readonly PROTOCOL_VERSION = 2;
/// <summary>
/// Minimal protocol version that is still supported.
/// V 1 servers won't understand heartbeat and version
/// messages but would just log an unknown message and
/// continue normally.
/// </summary>
public static readonly PROTOCOL_VERSION_MIN = 1;
/// <summary>
/// Assume 1 until message received
/// </summary>
private mRemoteProtocolVersion = 1;
private mUrl: string = null; private mUrl: string = null;
private mConfig: WebsocketNetwork.Configuration;
private mLastHeartbeat: number;
private mHeartbeatReceived = true;
private mIsDisposed = false; private mIsDisposed = false;
public constructor(url: string) { public constructor(url: string, configuration?:WebsocketNetwork.Configuration) {
this.mUrl = url; this.mUrl = url;
this.mStatus = WebsocketConnectionStatus.NotConnected; this.mStatus = WebsocketConnectionStatus.NotConnected;
this.mConfig = configuration;
if(!this.mConfig)
this.mConfig = new WebsocketNetwork.Configuration();
this.mConfig.Lock();
} }
private WebsocketConnect(): void { private WebsocketConnect(): void {
...@@ -90,7 +120,6 @@ export class WebsocketNetwork implements IBasicNetwork { ...@@ -90,7 +120,6 @@ export class WebsocketNetwork implements IBasicNetwork {
this.mSocket.onerror = (error) => { this.OnWebsocketOnError(error); }; this.mSocket.onerror = (error) => { this.OnWebsocketOnError(error); };
this.mSocket.onmessage = (e) => { this.OnWebsocketOnMessage(e); }; this.mSocket.onmessage = (e) => { this.OnWebsocketOnMessage(e); };
this.mSocket.onclose = (e) => { this.OnWebsocketOnClose(e); }; this.mSocket.onclose = (e) => { this.OnWebsocketOnClose(e); };
//js websockets connect automatically after creation?
} }
private WebsocketCleanup() : void { private WebsocketCleanup() : void {
this.mSocket.onopen = null; this.mSocket.onopen = null;
...@@ -114,7 +143,33 @@ export class WebsocketNetwork implements IBasicNetwork { ...@@ -114,7 +143,33 @@ export class WebsocketNetwork implements IBasicNetwork {
this.WebsocketConnect(); this.WebsocketConnect();
} }
} }
private UpdateHeartbeat():void{
if(this.mStatus == WebsocketConnectionStatus.Connected && this.mConfig.Heartbeat > 0)
{
let diff = Date.now() - this.mLastHeartbeat;
if(diff > (this.mConfig.Heartbeat * 1000))
{
//We trigger heatbeat timeouts only for protocol V2
//protocol 1 can receive the heatbeats but
//won't send a reply
//(still helpful to trigger TCP ACK timeout)
if(this.mRemoteProtocolVersion > 1
&& this.mHeartbeatReceived == false)
{
this.TriggerHeartbeatTimeout();
return;
}
this.mLastHeartbeat = Date.now();
this.mHeartbeatReceived = false;
this.SendHeartbeat();
}
}
}
private TriggerHeartbeatTimeout(){
SLog.L("Closing due to heartbeat timeout. Server didn't respond in time.", WebsocketNetwork.LOGTAG);
this.Cleanup();
}
private CheckSleep() : void private CheckSleep() : void
{ {
if (this.mStatus == WebsocketConnectionStatus.Connected if (this.mStatus == WebsocketConnectionStatus.Connected
...@@ -131,11 +186,13 @@ export class WebsocketNetwork implements IBasicNetwork { ...@@ -131,11 +186,13 @@ export class WebsocketNetwork implements IBasicNetwork {
private OnWebsocketOnOpen() { private OnWebsocketOnOpen() {
SLog.L('onWebsocketOnOpen'); SLog.L('onWebsocketOnOpen', WebsocketNetwork.LOGTAG);
this.mStatus = WebsocketConnectionStatus.Connected; this.mStatus = WebsocketConnectionStatus.Connected;
this.mLastHeartbeat = Date.now();
this.SendVersion();
} }
private OnWebsocketOnClose(event: CloseEvent) { private OnWebsocketOnClose(event: CloseEvent) {
SLog.L('Closed: ' + JSON.stringify(event)); SLog.L('Closed: ' + JSON.stringify(event), WebsocketNetwork.LOGTAG);
if(event.code != 1000) if(event.code != 1000)
{ {
...@@ -154,10 +211,9 @@ export class WebsocketNetwork implements IBasicNetwork { ...@@ -154,10 +211,9 @@ export class WebsocketNetwork implements IBasicNetwork {
|| this.mStatus == WebsocketConnectionStatus.NotConnected) || this.mStatus == WebsocketConnectionStatus.NotConnected)
return; return;
//browsers will have ArrayBuffer in event.data -> change to byte array //browsers will have ArrayBuffer in event.data -> change to byte array
let evt = NetworkEvent.fromByteArray(new Uint8Array(event.data)); let msg = new Uint8Array(event.data);
this.HandleIncomingEvent(evt); this.ParseMessage(msg);
} }
private OnWebsocketOnError(error) { private OnWebsocketOnError(error) {
//the error event doesn't seem to have any useful information? //the error event doesn't seem to have any useful information?
//browser is expected to call OnClose after this //browser is expected to call OnClose after this
...@@ -244,6 +300,31 @@ export class WebsocketNetwork implements IBasicNetwork { ...@@ -244,6 +300,31 @@ export class WebsocketNetwork implements IBasicNetwork {
this.mConnections.splice(index, 1); this.mConnections.splice(index, 1);
} }
} }
private ParseMessage(msg:Uint8Array):void{
if(msg.length == 0)
{
}else if(msg[0] == NetEventType.MetaVersion)
{
if (msg.length > 1)
{
this.mRemoteProtocolVersion = msg[1];
}
else
{
SLog.LW("Received an invalid MetaVersion header without content.");
}
}else if(msg[0] == NetEventType.MetaHeartbeat)
{
this.mHeartbeatReceived = true;
}else
{
let evt = NetworkEvent.fromByteArray(msg);
this.HandleIncomingEvent(evt);
}
}
private HandleIncomingEvent(evt: NetworkEvent) { private HandleIncomingEvent(evt: NetworkEvent) {
if (evt.Type == NetEventType.NewConnection) { if (evt.Type == NetEventType.NewConnection) {
...@@ -283,13 +364,38 @@ export class WebsocketNetwork implements IBasicNetwork { ...@@ -283,13 +364,38 @@ export class WebsocketNetwork implements IBasicNetwork {
while (this.mOutgoingQueue.length > 0) { while (this.mOutgoingQueue.length > 0) {
var evt = this.mOutgoingQueue.shift(); var evt = this.mOutgoingQueue.shift();
//var msg = NetworkEvent.toString(evt); this.SendNetworkEvent(evt);
var msg = NetworkEvent.toByteArray(evt);
this.mSocket.send(msg);
} }
} }
private SendHeartbeat() : void
{
let msg = new Uint8Array(1);
msg[0] = NetEventType.MetaHeartbeat;
this.InternalSend(msg);
}
private SendVersion() :void
{
let msg = new Uint8Array(2);
msg[0] = NetEventType.MetaVersion;
msg[1] = WebsocketNetwork.PROTOCOL_VERSION;
this.InternalSend(msg);
}
private SendNetworkEvent(evt: NetworkEvent):void
{
var msg = NetworkEvent.toByteArray(evt);
this.InternalSend(msg);
}
private InternalSend(msg: Uint8Array): void
{
this.mSocket.send(msg);
}
private NextConnectionId(): ConnectionId { private NextConnectionId(): ConnectionId {
var result = this.mNextOutgoingConnectionId; var result = this.mNextOutgoingConnectionId;
this.mNextOutgoingConnectionId = new ConnectionId(this.mNextOutgoingConnectionId.id + 1); this.mNextOutgoingConnectionId = new ConnectionId(this.mNextOutgoingConnectionId.id + 1);
...@@ -320,9 +426,11 @@ export class WebsocketNetwork implements IBasicNetwork { ...@@ -320,9 +426,11 @@ export class WebsocketNetwork implements IBasicNetwork {
return null; return null;
} }
public Update(): void { public Update(): void {
this.UpdateHeartbeat();
this.CheckSleep(); this.CheckSleep();
} }
public Flush(): void { public Flush(): void {
//ideally we buffer everything and then flush when it is connected as //ideally we buffer everything and then flush when it is connected as
//websockets aren't suppose to be used for realtime communication anyway //websockets aren't suppose to be used for realtime communication anyway
...@@ -395,6 +503,34 @@ export class WebsocketNetwork implements IBasicNetwork { ...@@ -395,6 +503,34 @@ export class WebsocketNetwork implements IBasicNetwork {
} }
} }
export namespace WebsocketNetwork{
export class Configuration{
mHeartbeat:number = 30;
get Heartbeat():number
{
return this.mHeartbeat;
}
set Heartbeat(value:number){
if(this.mLocked)
{
throw new Error("Can't change configuration once used.");
}
this.mHeartbeat = value;
}
mLocked = false;
Lock():void
{
this.mLocked = true;
}
}
}
//Below tests only. Move out later //Below tests only. Move out later
function bufferToString(buffer: Uint8Array): string { function bufferToString(buffer: Uint8Array): string {
...@@ -411,4 +547,4 @@ function stringToBuffer(str: string): Uint8Array { ...@@ -411,4 +547,4 @@ function stringToBuffer(str: string): Uint8Array {
let result = new Uint8Array(buf); let result = new Uint8Array(buf);
return result; return result;
} }
\ No newline at end of file
...@@ -74,7 +74,9 @@ describe("BrowserApiTest_MediaStreamApi", () => { ...@@ -74,7 +74,9 @@ describe("BrowserApiTest_MediaStreamApi", () => {
console.log(device.kind + ": " + device.label + console.log(device.kind + ": " + device.label +
" id = " + device.deviceId); " id = " + device.deviceId);
}); });
gStream.stop(); gStream.getTracks().forEach(t => {
t.stop();
});
done(); done();
}) })
.catch(function(err) { .catch(function(err) {
...@@ -109,7 +111,9 @@ describe("BrowserApiTest_MediaStreamApi", () => { ...@@ -109,7 +111,9 @@ describe("BrowserApiTest_MediaStreamApi", () => {
console.log(device.kind + ": " + device.label + console.log(device.kind + ": " + device.label +
" id = " + device.deviceId); " id = " + device.deviceId);
}); });
gStream.stop(); gStream.getTracks().forEach(t => {
t.stop();
});
done(); done();
}) })
.catch(function(err) { .catch(function(err) {
......
...@@ -31,6 +31,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -31,6 +31,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import {DeviceApi, CAPI_DeviceApi_Update, import {DeviceApi, CAPI_DeviceApi_Update,
CAPI_DeviceApi_RequestUpdate, CAPI_DeviceApi_Devices_Length, CAPI_DeviceApi_RequestUpdate, CAPI_DeviceApi_Devices_Length,
CAPI_DeviceApi_Devices_Get} from "../awrtc/index" CAPI_DeviceApi_Devices_Get} from "../awrtc/index"
export function DeviceApiTest_export() export function DeviceApiTest_export()
{ {
...@@ -97,7 +98,7 @@ describe("DeviceApiTest", () => { ...@@ -97,7 +98,7 @@ describe("DeviceApiTest", () => {
//should have original label now //should have original label now
expect(devices2[key1].label).not.toBe("videodevice 1"); expect(devices2[key1].label).not.toBe("videodevice 1");
//and not be guessed anymore //and not be guessed anymore
expect(devices2[key1].isLabelGuessed).toBe(false); expect(devices2[key1].isLabelGuessed).toBe(false, "Chrome fails this now. Likely due to file://. Check for better test setup");
update2complete = true; update2complete = true;
DeviceApi.Reset(); DeviceApi.Reset();
......
...@@ -30,7 +30,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -30,7 +30,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import { WebsocketTest } from "WebsocketNetworkTest"; import { WebsocketTest } from "WebsocketNetworkTest";
import { IBasicNetworkTest } from "helper/IBasicNetworkTest"; import { IBasicNetworkTest } from "helper/IBasicNetworkTest";
import { NetworkEvent, IBasicNetwork, NetEventType, WebsocketNetwork, import { NetworkEvent, IBasicNetwork, NetEventType, WebsocketNetwork,
ConnectionId, SignalingConfig, LocalNetwork, WebRtcNetwork } ConnectionId, SignalingConfig, LocalNetwork, WebRtcNetwork, IWebRtcNetwork }
from "../awrtc/index"; from "../awrtc/index";
export class WebRtcNetworkTest extends IBasicNetworkTest { export class WebRtcNetworkTest extends IBasicNetworkTest {
...@@ -56,6 +56,46 @@ export class WebRtcNetworkTest extends IBasicNetworkTest { ...@@ -56,6 +56,46 @@ export class WebRtcNetworkTest extends IBasicNetworkTest {
this.mUrl = WebsocketTest.sUrl; this.mUrl = WebsocketTest.sUrl;
this.mUseWebsockets = WebRtcNetworkTest.mAlwaysUseWebsockets; this.mUseWebsockets = WebRtcNetworkTest.mAlwaysUseWebsockets;
}) })
it("GetBufferedAmount", (done) => {
var srv: IWebRtcNetwork;
var address: string;
var srvToCltId: ConnectionId;
var clt: IWebRtcNetwork;
var cltToSrvId: ConnectionId;
var evt: NetworkEvent;
this.thenAsync((finished) => {
this._CreateServerClient((rsrv, raddress, rsrvToCltId, rclt, rcltToSrvId) => {
srv = rsrv as IWebRtcNetwork;
address = raddress;
srvToCltId = rsrvToCltId;
clt = rclt as IWebRtcNetwork;
cltToSrvId = rcltToSrvId;
finished();
});
});
this.then(() => {
//TODO: more detailed testing by actually triggering the buffer to fill?
//might be tricky as this is very system dependent
let buf:number;
buf = srv.GetBufferedAmount(srvToCltId, false);
expect(buf).toBe(0);
buf = srv.GetBufferedAmount(srvToCltId, true);
expect(buf).toBe(0);
buf = clt.GetBufferedAmount(cltToSrvId, false);
expect(buf).toBe(0);
buf = clt.GetBufferedAmount(cltToSrvId, true);
expect(buf).toBe(0);
done();
});
this.start();
});
it("SharedAddress", (done) => { it("SharedAddress", (done) => {
//turn off websockets and use shared websockets for this test as local network doesn't support shared mode //turn off websockets and use shared websockets for this test as local network doesn't support shared mode
......
...@@ -40,6 +40,7 @@ export class WebsocketTest extends IBasicNetworkTest { ...@@ -40,6 +40,7 @@ export class WebsocketTest extends IBasicNetworkTest {
//public static sUrl = 'ws://localhost:12776/test'; //public static sUrl = 'ws://localhost:12776/test';
//public static sUrlShared = 'ws://localhost:12776/testshared'; //public static sUrlShared = 'ws://localhost:12776/testshared';
public static sUrl = 'ws://signaling.because-why-not.com'; public static sUrl = 'ws://signaling.because-why-not.com';
//public static sUrl = 'ws://192.168.1.3:12776';
public static sUrlShared = 'ws://signaling.because-why-not.com/testshared'; public static sUrlShared = 'ws://signaling.because-why-not.com/testshared';
//any url to simulate offline server //any url to simulate offline server
public static sBadUrl = 'ws://localhost:13776'; public static sBadUrl = 'ws://localhost:13776';
...@@ -54,6 +55,42 @@ export class WebsocketTest extends IBasicNetworkTest { ...@@ -54,6 +55,42 @@ export class WebsocketTest extends IBasicNetworkTest {
this.mUrl = WebsocketTest.sUrl; this.mUrl = WebsocketTest.sUrl;
}); });
//can only be done manually so far
xit("Timeout", (done) => {
//this needs to be a local test server
//that can be disconnected to test the timeout
this.mUrl = "ws://192.168.1.3:12776";
var evt: NetworkEvent;
var srv: WebsocketNetwork;
var address;
this.thenAsync((finished) => {
this._CreateServerNetwork((rsrv, raddress) => {
srv = rsrv;
address = raddress;
finished();
});
});
this.thenAsync((finished) => {
console.log("Server ready at " + address);
expect(srv).not.toBeNull();
expect(address).not.toBeNull();
console.debug("Waiting for timeout");
this.waitForEvent(srv, finished, 120000);
});
this.then(() => {
console.log("Timeout over");
evt = srv.Dequeue();
expect(evt).not.toBeNull();
expect(evt.Type).toBe(NetEventType.ServerClosed);
expect(srv.getStatus()).toBe(WebsocketConnectionStatus.NotConnected);
done();
});
this.start();
}, 130000);
it("SharedAddress", (done) => { it("SharedAddress", (done) => {
this.mUrl = WebsocketTest.sUrlShared; this.mUrl = WebsocketTest.sUrlShared;
......
...@@ -28,7 +28,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ...@@ -28,7 +28,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
import { BasicNetworkTestBase, Task } from "./BasicNetworkTestBase"; import { BasicNetworkTestBase, Task } from "./BasicNetworkTestBase";
import { IBasicNetwork, NetworkEvent, NetEventType, ConnectionId, Encoding } from "../../awrtc/network/index"; import { IBasicNetwork, NetworkEvent, NetEventType, ConnectionId, Encoding, SLog, SLogLevel } from "../../awrtc/network/index";
export abstract class IBasicNetworkTest extends BasicNetworkTestBase { export abstract class IBasicNetworkTest extends BasicNetworkTestBase {
...@@ -36,10 +36,12 @@ export abstract class IBasicNetworkTest extends BasicNetworkTestBase { ...@@ -36,10 +36,12 @@ export abstract class IBasicNetworkTest extends BasicNetworkTestBase {
super.setup(); super.setup();
let originalTimeout = 5000; let originalTimeout = 5000;
beforeEach(() => { beforeEach(() => {
SLog.RequestLogLevel(SLogLevel.Info);
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = this.mDefaultWaitTimeout + 5000; jasmine.DEFAULT_TIMEOUT_INTERVAL = this.mDefaultWaitTimeout + 5000;
}); });
afterEach(() => { afterEach(() => {
console.debug("Test shutting down ...");
this.ShutdownAll(); this.ShutdownAll();
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = this.mDefaultWaitTimeout + 5000; jasmine.DEFAULT_TIMEOUT_INTERVAL = this.mDefaultWaitTimeout + 5000;
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
"WebRtcNetworkTest.ts", "WebRtcNetworkTest.ts",
"CallTest.ts", "CallTest.ts",
"LocalNetworkTest.ts", "LocalNetworkTest.ts",
"MediaNetworkTest.ts" "MediaNetworkTest.ts",
"DeviceApiTest.ts",
"BrowserApiTest.ts"
] ]
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment