aotrautils 0.0.1795 → 0.0.1797
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.
- aotrautils/aotrautils.build.js +324 -270
- aotrautils/package.json +1 -1
aotrautils/aotrautils.build.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
/*utils COMMONS library associated with aotra version : «1_29072022-2359 (
|
|
3
|
+
/*utils COMMONS library associated with aotra version : «1_29072022-2359 (11/11/2025-17:05:51)»*/
|
|
4
4
|
/*-----------------------------------------------------------------------------*/
|
|
5
5
|
|
|
6
6
|
|
|
@@ -1618,7 +1618,7 @@ aotest.profile=function(rootObject,methodName,visited=[]){
|
|
|
1618
1618
|
|
|
1619
1619
|
|
|
1620
1620
|
//================================================================
|
|
1621
|
-
//=================
|
|
1621
|
+
//================= Thread control utility methods =================
|
|
1622
1622
|
//================================================================
|
|
1623
1623
|
|
|
1624
1624
|
|
|
@@ -3868,7 +3868,7 @@ Math.makeMultipleOf=function(bruteValue, multiple,/*OPTIONAL*/roundingMode){
|
|
|
3868
3868
|
|
|
3869
3869
|
|
|
3870
3870
|
getTimer=function(callback, delay){
|
|
3871
|
-
return new
|
|
3871
|
+
return new SimpleTimer(callback, delay);
|
|
3872
3872
|
// let self={
|
|
3873
3873
|
// timerId:null,
|
|
3874
3874
|
// start:null,
|
|
@@ -3893,14 +3893,14 @@ getTimer=function(callback, delay){
|
|
|
3893
3893
|
|
|
3894
3894
|
|
|
3895
3895
|
//Usage :
|
|
3896
|
-
//var timer=new
|
|
3896
|
+
//var timer=new SimpleTimer(function(){
|
|
3897
3897
|
//alert("Done!");
|
|
3898
3898
|
//}, 1000);
|
|
3899
3899
|
//
|
|
3900
3900
|
//timer.pause();
|
|
3901
3901
|
////Do some stuff...
|
|
3902
3902
|
//timer.resume();
|
|
3903
|
-
var
|
|
3903
|
+
var SimpleTimer=function(callback, delay){
|
|
3904
3904
|
var timerId, start, remaining=delay;
|
|
3905
3905
|
|
|
3906
3906
|
this.pause=function(){
|
|
@@ -5002,6 +5002,38 @@ window.splitURL=(urlOrigin)=>{
|
|
|
5002
5002
|
return {protocol:protocol, host:host, port:port, isSecure:isSecure};
|
|
5003
5003
|
};
|
|
5004
5004
|
|
|
5005
|
+
window.getPathExtension=(path)=>{
|
|
5006
|
+
const splits = path.split(".");
|
|
5007
|
+
if(splits.length <= 1)
|
|
5008
|
+
return "";
|
|
5009
|
+
return splits.pop();
|
|
5010
|
+
}
|
|
5011
|
+
|
|
5012
|
+
window.getBasePath=(pathParam, fileSeparator="/")=>{
|
|
5013
|
+
// Clean :
|
|
5014
|
+
const path=pathParam.replace(/\/{2,}/gim,"/");
|
|
5015
|
+
const splits = path.split(fileSeparator);
|
|
5016
|
+
if(splits.length <= 1)
|
|
5017
|
+
return path;
|
|
5018
|
+
// We remove the last part, corresponding to the file name:
|
|
5019
|
+
return splits.slice(0,-1).join(fileSeparator)+fileSeparator;
|
|
5020
|
+
}
|
|
5021
|
+
|
|
5022
|
+
window.getPathFileName=(path, fileSeparator="/", removeExtension=false)=>{
|
|
5023
|
+
const splits = path.split(fileSeparator);
|
|
5024
|
+
if(splits.length <= 0)
|
|
5025
|
+
return "";
|
|
5026
|
+
let fileNameWithExtension=splits.pop();
|
|
5027
|
+
if(empty(fileNameWithExtension))
|
|
5028
|
+
return "";
|
|
5029
|
+
if(!removeExtension)
|
|
5030
|
+
return fileNameWithExtension;
|
|
5031
|
+
const fileNameSplits = fileNameWithExtension.split(".");
|
|
5032
|
+
if(fileNameSplits.length <= 0)
|
|
5033
|
+
return "";
|
|
5034
|
+
return fileNameSplits[0];
|
|
5035
|
+
}
|
|
5036
|
+
|
|
5005
5037
|
|
|
5006
5038
|
|
|
5007
5039
|
// MUST REMAIN AT THE END OF THIS LIBRARY FILE !
|
|
@@ -5012,7 +5044,7 @@ AOTRAUTILS_LIB_IS_LOADED=true;
|
|
|
5012
5044
|
|
|
5013
5045
|
|
|
5014
5046
|
|
|
5015
|
-
/*utils CLIENT library associated with aotra version : «1_29072022-2359 (
|
|
5047
|
+
/*utils CLIENT library associated with aotra version : «1_29072022-2359 (11/11/2025-17:05:51)»*/
|
|
5016
5048
|
/*-----------------------------------------------------------------------------*/
|
|
5017
5049
|
/* ## Utility global methods in a browser (htmljs) client environment.
|
|
5018
5050
|
*
|
|
@@ -7949,55 +7981,84 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
7949
7981
|
/*OPTIONAL*/tagConfig={},
|
|
7950
7982
|
/*OPTIONAL*/audioBufferSize=null,/*OPTIONAL*/numberOfAudioChannels=null,
|
|
7951
7983
|
/*OPTIONAL*/doOnStart=null,
|
|
7952
|
-
/*OPTIONAL*/doFinallyWhenMultipleDevices=null
|
|
7984
|
+
/*OPTIONAL*//*DEPRECATED : USE PROMISE then() INSTEAD*/doFinallyWhenMultipleDevices=null
|
|
7953
7985
|
){
|
|
7954
7986
|
|
|
7987
|
+
|
|
7955
7988
|
if(!isUserMediaAvailable()){
|
|
7956
7989
|
// TRACE
|
|
7957
7990
|
log("ERROR : User medias is not supported in your browser (or are you running in a non-https context ?). Aborting");
|
|
7958
|
-
return
|
|
7991
|
+
return new Promise();
|
|
7959
7992
|
}
|
|
7960
|
-
|
|
7961
|
-
const cameras=[];
|
|
7962
|
-
const microphones=[];
|
|
7963
|
-
navigator.mediaDevices.enumerateDevices().then(function(devices){
|
|
7964
7993
|
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7994
|
+
return new Promise((accept,reject)=>{
|
|
7995
|
+
|
|
7996
|
+
// Force request permissions :
|
|
7997
|
+
const constraints={video:(videoConfigParam!=null), audio:(audioConfigParam!=null)}; // Default constraints (corresponding to no media)
|
|
7998
|
+
navigator.mediaDevices.getUserMedia(constraints).then(()=>{
|
|
7999
|
+
|
|
7969
8000
|
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
8001
|
+
const cameras=[];
|
|
8002
|
+
const microphones=[];
|
|
8003
|
+
|
|
8004
|
+
navigator.mediaDevices.enumerateDevices().then(function(devices){
|
|
8005
|
+
|
|
8006
|
+
// DBG
|
|
8007
|
+
lognow("DEBUG : Devices :",devices);
|
|
8008
|
+
|
|
8009
|
+
devices.forEach(function(d){
|
|
8010
|
+
if(d.kind==="videoinput") cameras.push(d);
|
|
8011
|
+
else if(d.kind==="audioinput") microphones.push(d);
|
|
8012
|
+
});
|
|
8013
|
+
|
|
8014
|
+
// CAUTION : On today this method only handles media handlers with a single track :
|
|
8015
|
+
|
|
8016
|
+
if(videoConfigParam){
|
|
8017
|
+
if(!empty(cameras)){
|
|
8018
|
+
let webcamIndex=videoConfigParam.webcamIndex;
|
|
8019
|
+
if(webcamIndex!=null && isNumber(webcamIndex)){
|
|
8020
|
+
const deviceIndex=Math.min(cameras.length-1, webcamIndex);
|
|
8021
|
+
constraints.video={ deviceId:{ exact: cameras[deviceIndex].deviceId } };
|
|
7980
8022
|
}
|
|
7981
|
-
}
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
8023
|
+
}else{
|
|
8024
|
+
// TRACE
|
|
8025
|
+
lognow("ERROR : Video requested but no camera found. Aborting.");
|
|
8026
|
+
constraints.video=false;
|
|
8027
|
+
}
|
|
8028
|
+
}
|
|
8029
|
+
if(audioConfigParam){
|
|
8030
|
+
if(!empty(microphones)){
|
|
8031
|
+
let microphoneIndex=audioConfigParam.microphoneIndex;
|
|
8032
|
+
if(microphoneIndex!=null && isNumber(microphoneIndex)){
|
|
8033
|
+
const deviceIndex=Math.min(microphones.length-1, microphoneIndex);
|
|
8034
|
+
constraints.audio={ deviceId: { exact: microphones[deviceIndex].deviceId } };
|
|
7990
8035
|
}
|
|
7991
|
-
}
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
8036
|
+
}else{
|
|
8037
|
+
// TRACE
|
|
8038
|
+
lognow("ERROR : Audio requested but no microphone found. Aborting.");
|
|
8039
|
+
constraints.audio=false;
|
|
8040
|
+
}
|
|
8041
|
+
}
|
|
8042
|
+
|
|
8043
|
+
|
|
8044
|
+
let mediaHandler=getMediaHandlerIMPL(constraints, size, tagConfig, audioBufferSize, numberOfAudioChannels, doOnStart, {cameras:cameras, microphones:microphones});
|
|
8045
|
+
if(doFinallyWhenMultipleDevices) doFinallyWhenMultipleDevices(mediaHandler);
|
|
8046
|
+
|
|
8047
|
+
accept(mediaHandler);
|
|
8048
|
+
|
|
8049
|
+
}).catch(err=>{
|
|
8050
|
+
// TRACE
|
|
8051
|
+
lognow("ERROR : An error occured when trying to enumerate devices:",err);
|
|
8052
|
+
reject(err);
|
|
8053
|
+
});
|
|
7995
8054
|
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8055
|
+
}).catch(err=>{
|
|
8056
|
+
// TRACE
|
|
8057
|
+
lognow("ERROR : An error occured when trying to get webcam handler:",err);
|
|
8058
|
+
reject(err);
|
|
8059
|
+
});
|
|
8000
8060
|
|
|
8061
|
+
});
|
|
8001
8062
|
|
|
8002
8063
|
};
|
|
8003
8064
|
|
|
@@ -8037,18 +8098,22 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
8037
8098
|
// 0- Basic validation :
|
|
8038
8099
|
if(!mediaConstraints){
|
|
8039
8100
|
// TRACE
|
|
8040
|
-
log("ERROR :
|
|
8101
|
+
log("ERROR : No media constraint has been set for this mediaHandler !");
|
|
8041
8102
|
return null;
|
|
8042
8103
|
}
|
|
8104
|
+
|
|
8105
|
+
|
|
8106
|
+
|
|
8043
8107
|
const isVideo=!!(mediaConstraints.video);
|
|
8044
8108
|
const isAudio=!!(mediaConstraints.audio);
|
|
8045
8109
|
if(!isVideo && !isAudio){
|
|
8046
8110
|
// TRACE
|
|
8047
|
-
log("ERROR :
|
|
8111
|
+
log("ERROR : No audio nor video has been selected for this mediaHandler !");
|
|
8048
8112
|
return null;
|
|
8049
8113
|
}
|
|
8050
8114
|
|
|
8051
8115
|
|
|
8116
|
+
|
|
8052
8117
|
if(!isUserMediaAvailable()){
|
|
8053
8118
|
// TRACE
|
|
8054
8119
|
log("ERROR : User medias is not supported in your browser (or are you running in a non-https context ?). Aborting");
|
|
@@ -8066,14 +8131,19 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
8066
8131
|
devicesInfo:devicesInfo,
|
|
8067
8132
|
// UNUSED : mediaConstraints:mediaConstraints,
|
|
8068
8133
|
// technical attributes :
|
|
8069
|
-
|
|
8134
|
+
videoReadingElement:null, // This is where you will read the video image data !
|
|
8135
|
+
|
|
8136
|
+
// // DOES NOT WORK WELL :
|
|
8137
|
+
// imageReader:null,
|
|
8138
|
+
// currentVideoFrame:null,
|
|
8139
|
+
|
|
8070
8140
|
canvasTag:null,
|
|
8071
8141
|
canvasCtx:null,
|
|
8072
8142
|
audioData:[],// Where to store sound data
|
|
8073
8143
|
audioCtx:null,
|
|
8074
8144
|
|
|
8075
|
-
videoDeviceId:(mediaConstraints.video?mediaConstraints.video.deviceId.exact:null),
|
|
8076
|
-
audioDeviceId:(mediaConstraints.audio?mediaConstraints.audio.deviceId.exact:null),
|
|
8145
|
+
videoDeviceId:(mediaConstraints.video && mediaConstraints.video.deviceId?mediaConstraints.video.deviceId.exact:null),
|
|
8146
|
+
audioDeviceId:(mediaConstraints.audio && mediaConstraints.audio.deviceId?mediaConstraints.audio.deviceId.exact:null),
|
|
8077
8147
|
|
|
8078
8148
|
imageInterceptors:[],
|
|
8079
8149
|
appendImageInterceptor:(method)=>mediaHandler.imageInterceptors.push(method),
|
|
@@ -8102,36 +8172,40 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
8102
8172
|
//canvasTag.style.display="none";
|
|
8103
8173
|
|
|
8104
8174
|
|
|
8105
|
-
|
|
8106
|
-
let videoTag;
|
|
8175
|
+
let videoTag=null;
|
|
8107
8176
|
if(!tagConfig || !tagConfig.videoToUse){
|
|
8108
|
-
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
//
|
|
8177
|
+
|
|
8178
|
+
// // DOES NOT WORK WELL :
|
|
8179
|
+
// if(!tagConfig.useNoVideoReadingElement){
|
|
8180
|
+
|
|
8181
|
+
// This temporary, off-screen video is always needed to get the image data for further use :
|
|
8182
|
+
videoTag=document.createElement("video");
|
|
8183
|
+
videoTag.id="tmpVideoElement";
|
|
8184
|
+
videoTag.autoplay=true;
|
|
8185
|
+
videoTag.width=canvasTag.width;
|
|
8186
|
+
videoTag.height=canvasTag.height;
|
|
8187
|
+
videoTag.style.width=canvasTag.width+"px";
|
|
8188
|
+
videoTag.style.height=canvasTag.height+"px";
|
|
8189
|
+
|
|
8190
|
+
// // UNUSEFUL (SINCE VIDEO ELEMENT IS NEVER APPENDED TO PAGE !) :
|
|
8191
|
+
// videoTag.style.position="absolute";
|
|
8192
|
+
// videoTag.style["pointer-events"]="none";
|
|
8193
|
+
// videoTag.style.display="none";
|
|
8194
|
+
// videoTag.style.display="none";
|
|
8195
|
+
// document.body.appendChild(videoTag);
|
|
8196
|
+
// }
|
|
8122
8197
|
|
|
8123
8198
|
}else{
|
|
8124
8199
|
videoTag=tagConfig.videoToUse;
|
|
8125
8200
|
}
|
|
8126
8201
|
|
|
8127
|
-
|
|
8128
8202
|
|
|
8129
|
-
mediaHandler.
|
|
8203
|
+
mediaHandler.videoReadingElement=videoTag;
|
|
8130
8204
|
|
|
8131
8205
|
|
|
8132
8206
|
// UNUSED
|
|
8133
8207
|
// mediaHandler.isReady=function(){
|
|
8134
|
-
//// return mediaHandler.
|
|
8208
|
+
//// return mediaHandler.videoReadingElement !== null;
|
|
8135
8209
|
// return !!(mediaHandler.stream);
|
|
8136
8210
|
// };
|
|
8137
8211
|
|
|
@@ -8141,8 +8215,7 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
8141
8215
|
if(!constraints){
|
|
8142
8216
|
//constraints={video: (isVideo?{zoom:true,width:{ideal:nonull(width,DEFAULT_WIDTH)},height:{ideal:nonull(height,DEFAULT_HEIGHT)}}:false), audio: isAudio};
|
|
8143
8217
|
// DBG
|
|
8144
|
-
constraints={video: (isVideo?
|
|
8145
|
-
{width:nonull(width,DEFAULT_WIDTH),height:nonull(height,DEFAULT_HEIGHT)}
|
|
8218
|
+
constraints={video: (isVideo?{width:{ideal:nonull(width,DEFAULT_WIDTH)},height:{ideal:nonull(height,DEFAULT_HEIGHT)} }
|
|
8146
8219
|
//// ALTERNATIVELY, AND MORE FINE_TUNED :
|
|
8147
8220
|
// {zoom:true,mandatory: {
|
|
8148
8221
|
// minWidth: 1280,
|
|
@@ -8152,6 +8225,24 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
8152
8225
|
// }
|
|
8153
8226
|
// }
|
|
8154
8227
|
:false), audio: isAudio};
|
|
8228
|
+
}else{
|
|
8229
|
+
|
|
8230
|
+
if(isVideo){
|
|
8231
|
+
if(!constraints.video){
|
|
8232
|
+
constraints.video={};
|
|
8233
|
+
}
|
|
8234
|
+
if(!constraints.video.width){
|
|
8235
|
+
constraints.video.width={ideal:nonull(width,DEFAULT_WIDTH)};
|
|
8236
|
+
}
|
|
8237
|
+
if(!constraints.video.height){
|
|
8238
|
+
constraints.video.height={ideal:nonull(height,DEFAULT_HEIGHT)};
|
|
8239
|
+
}
|
|
8240
|
+
}
|
|
8241
|
+
if(isAudio && !constraints.audio){
|
|
8242
|
+
constraints.audio=true;
|
|
8243
|
+
}
|
|
8244
|
+
|
|
8245
|
+
|
|
8155
8246
|
}
|
|
8156
8247
|
|
|
8157
8248
|
// TRACE
|
|
@@ -8168,9 +8259,9 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
8168
8259
|
|
|
8169
8260
|
|
|
8170
8261
|
// DBG
|
|
8171
|
-
lognow("
|
|
8172
|
-
lognow("
|
|
8173
|
-
lognow("
|
|
8262
|
+
lognow("DEBUG : streamSettings:",streamSettings);
|
|
8263
|
+
lognow("DEBUG : stream:",stream);
|
|
8264
|
+
lognow("DEBUG : stream.getVideoTracks():",stream.getVideoTracks());
|
|
8174
8265
|
|
|
8175
8266
|
|
|
8176
8267
|
if(streamSettings){
|
|
@@ -8186,27 +8277,35 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
8186
8277
|
|
|
8187
8278
|
// TRACE
|
|
8188
8279
|
lognow("INFO : MEDIA HANDLER : Starting video...");
|
|
8189
|
-
|
|
8190
|
-
|
|
8191
|
-
|
|
8280
|
+
|
|
8281
|
+
// // DOES NOT WORK WELL :
|
|
8282
|
+
// if(tagConfig && tagConfig.useNoVideoReadingElement){
|
|
8283
|
+
//
|
|
8284
|
+
// const track = stream.getVideoTracks()[0];
|
|
8285
|
+
// const processor = new MediaStreamTrackProcessor({track});
|
|
8286
|
+
// const readableStream = processor.readable;
|
|
8287
|
+
// mediaHandler.imageReader = readableStream.getReader();
|
|
8288
|
+
//
|
|
8289
|
+
//
|
|
8290
|
+
// }else
|
|
8291
|
+
// In this case we have a single video tag for this mediaHandler (to grab the video data)
|
|
8292
|
+
if(!isArray(mediaHandler.videoReadingElement)){
|
|
8192
8293
|
|
|
8193
|
-
mediaHandler.
|
|
8294
|
+
mediaHandler.videoReadingElement.srcObject=stream;
|
|
8194
8295
|
// DOES NOT WORK : mediaHandler.video.src=stream;
|
|
8195
8296
|
|
|
8196
|
-
// NO : DOES NOT WORK (CREATES A BLANK IMAGE !) mediaHandler.
|
|
8297
|
+
// NO : DOES NOT WORK (CREATES A BLANK IMAGE !) mediaHandler.videoReadingElement.muted=true;
|
|
8197
8298
|
// STUPID WORKAROUND : Because apparently, if volume==0 or video is muted, then the image data is all black !!!
|
|
8198
|
-
mediaHandler.
|
|
8199
|
-
// mediaHandler.
|
|
8299
|
+
mediaHandler.videoReadingElement.volume=0.0000000000001;
|
|
8300
|
+
// mediaHandler.videoReadingElement.autoplay=true;
|
|
8200
8301
|
|
|
8201
|
-
if(tagConfig && tagConfig.videoToUse && tagConfig.videoScale){
|
|
8202
|
-
|
|
8203
|
-
mediaHandler.video.style.scale=tagConfig.videoScale;
|
|
8204
|
-
}
|
|
8302
|
+
if(tagConfig && tagConfig.videoToUse && tagConfig.videoScale && isNumber(tagConfig.videoScale)){
|
|
8303
|
+
mediaHandler.videoReadingElement.style.scale=tagConfig.videoScale;
|
|
8205
8304
|
}
|
|
8206
8305
|
|
|
8207
8306
|
}else{ // Audio part :
|
|
8208
8307
|
|
|
8209
|
-
foreach(mediaHandler.
|
|
8308
|
+
foreach(mediaHandler.videoReadingElement,(v)=>{
|
|
8210
8309
|
|
|
8211
8310
|
v.srcObject=stream;
|
|
8212
8311
|
|
|
@@ -8220,7 +8319,7 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
8220
8319
|
|
|
8221
8320
|
|
|
8222
8321
|
mediaHandler.canvasTag=canvasTag;
|
|
8223
|
-
mediaHandler.canvasCtx=mediaHandler.canvasTag.getContext("2d");
|
|
8322
|
+
mediaHandler.canvasCtx=mediaHandler.canvasTag.getContext("2d",{ willReadFrequently: true }/*CAUTION : DISABLES GPU OPTIMIZATION !*/);
|
|
8224
8323
|
|
|
8225
8324
|
let x=0;
|
|
8226
8325
|
let y=0;
|
|
@@ -8228,37 +8327,60 @@ function filterPoints(allPoints ,ctx/*DBG*/){
|
|
|
8228
8327
|
let width=mediaHandler.canvasTag.width;
|
|
8229
8328
|
let height=mediaHandler.canvasTag.height;
|
|
8230
8329
|
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8330
|
+
|
|
8331
|
+
// // DOES NOT WORK WELL :
|
|
8332
|
+
// if(tagConfig && tagConfig.useNoVideoReadingElement){
|
|
8333
|
+
//
|
|
8334
|
+
// mediaHandler.getVideoData=()=>{
|
|
8335
|
+
// if(mediaHandler.currentVideoFrame==null)
|
|
8336
|
+
// mediaHandler.imageReader.read().then((videoFrame)=>{
|
|
8337
|
+
// mediaHandler.currentVideoFrame=videoFrame.value;
|
|
8338
|
+
// });
|
|
8339
|
+
// currentVideoFrame=mediaHandler.currentVideoFrame;
|
|
8340
|
+
// mediaHandler.currentVideoFrame=null;
|
|
8341
|
+
// return currentVideoFrame;
|
|
8342
|
+
// };
|
|
8343
|
+
//
|
|
8344
|
+
// }else{
|
|
8345
|
+
|
|
8346
|
+
mediaHandler.getVideoData=function(){
|
|
8347
|
+
|
|
8348
|
+
// To read the image data : (code from «PlaneWebcamProvider.js»)
|
|
8349
|
+
// (in a canvas drawing function with canvasContext ctx :)
|
|
8350
|
+
|
|
8351
|
+
const ctx=mediaHandler.canvasCtx;
|
|
8237
8352
|
ctx.save();
|
|
8238
|
-
|
|
8353
|
+
const imageObj= (isArray(mediaHandler.videoReadingElement)?mediaHandler.videoReadingElement[0]:mediaHandler.videoReadingElement);
|
|
8239
8354
|
ctx.drawImage(imageObj,x,y,width,height);
|
|
8240
|
-
|
|
8355
|
+
const imageData=ctx.getImageData(x, y, width, height);
|
|
8356
|
+
imageData.messWithAlpha=true;
|
|
8241
8357
|
foreach(mediaHandler.imageInterceptors,(method)=>{method(imageData.data);});
|
|
8358
|
+
|
|
8242
8359
|
ctx.restore();
|
|
8243
|
-
|
|
8244
|
-
imageData.messWithAlpha=true;
|
|
8360
|
+
|
|
8245
8361
|
|
|
8246
8362
|
return imageData;// returns an object containing data in this form : {data:<image data array>, width:<image width>, height:<image height>, messWithAlpha:true}
|
|
8247
|
-
|
|
8363
|
+
};
|
|
8364
|
+
// }
|
|
8365
|
+
|
|
8366
|
+
|
|
8367
|
+
|
|
8368
|
+
|
|
8369
|
+
|
|
8248
8370
|
|
|
8249
8371
|
// If we have feed actual video visible tags, then we play them :
|
|
8250
8372
|
if(tagConfig && tagConfig.videoToUse && !tagConfig.invisibleVideoTag){
|
|
8251
8373
|
|
|
8252
8374
|
|
|
8253
|
-
if(!isArray(mediaHandler.
|
|
8254
|
-
mediaHandler.
|
|
8375
|
+
if(!isArray(mediaHandler.videoReadingElement)){
|
|
8376
|
+
mediaHandler.videoReadingElement.onloadedmetadata=function(event){
|
|
8255
8377
|
let video=event.target;
|
|
8256
8378
|
video.play();
|
|
8257
8379
|
if(tagConfig.videoMuted) video.muted=true;
|
|
8258
8380
|
else delete video.muted;
|
|
8259
8381
|
};
|
|
8260
8382
|
}else{
|
|
8261
|
-
foreach(mediaHandler.
|
|
8383
|
+
foreach(mediaHandler.videoReadingElement,(v)=>{
|
|
8262
8384
|
v.onloadedmetadata=function(event){
|
|
8263
8385
|
let video=event.target;
|
|
8264
8386
|
video.play();
|
|
@@ -8393,21 +8515,31 @@ drawVideoImage=function(canvas,videoImage,
|
|
|
8393
8515
|
/*OPTIONAL*/newWidthParam,/*OPTIONAL*/newHeightParam,
|
|
8394
8516
|
/*OPTIONAL*/isMessWithAlpha){
|
|
8395
8517
|
|
|
8396
|
-
|
|
8518
|
+
const ctx=canvas.getContext("2d");
|
|
8519
|
+
|
|
8520
|
+
var x=nonull(xParam,0);
|
|
8521
|
+
var y=nonull(yParam,0);
|
|
8522
|
+
|
|
8523
|
+
// // DOES NOT WORK WELL :
|
|
8524
|
+
// if(Object.getPrototypeOf(videoImage).constructor.name==="VideoFrame"){
|
|
8525
|
+
// ctx.drawImage(videoImage, x, y, newWidthParam, newHeightParam);
|
|
8526
|
+
// return;
|
|
8527
|
+
// }
|
|
8528
|
+
|
|
8397
8529
|
var oldWidth=videoImage.width;
|
|
8398
8530
|
var oldHeight=videoImage.height;
|
|
8399
8531
|
|
|
8400
|
-
var x=nonull(xParam,0);
|
|
8401
|
-
var y=nonull(yParam,0);
|
|
8402
8532
|
const zooms=nonull(zoomsParam,{zx:1,zy:1});
|
|
8403
8533
|
|
|
8404
8534
|
var newWidth=newWidthParam?newWidthParam:canvas.width;
|
|
8405
8535
|
var newHeight=newHeightParam?newHeightParam:canvas.height;
|
|
8406
8536
|
|
|
8407
|
-
var ctx=canvas.getContext("2d");
|
|
8408
8537
|
|
|
8409
8538
|
let imageData=null;
|
|
8410
8539
|
let tmpImage=null;
|
|
8540
|
+
|
|
8541
|
+
|
|
8542
|
+
const videoRawImageData=videoImage.data;
|
|
8411
8543
|
if(videoImage.format==="base64"){
|
|
8412
8544
|
|
|
8413
8545
|
tmpImage=new Image();
|
|
@@ -8422,6 +8554,9 @@ drawVideoImage=function(canvas,videoImage,
|
|
|
8422
8554
|
normalizeData(videoRawImageData, imageData.data, isMessWithAlpha);
|
|
8423
8555
|
|
|
8424
8556
|
}
|
|
8557
|
+
|
|
8558
|
+
|
|
8559
|
+
|
|
8425
8560
|
|
|
8426
8561
|
let clipX=0; // UNUSED
|
|
8427
8562
|
let clipY=0; // UNUSED
|
|
@@ -9676,7 +9811,7 @@ function arrayFromString(strParam,compressResult=true,precisionFraction=null,isS
|
|
|
9676
9811
|
// appendAsFirstChildOf(videoTag, backgroundContainerDiv);
|
|
9677
9812
|
//}
|
|
9678
9813
|
//
|
|
9679
|
-
//webcamHandler.
|
|
9814
|
+
//webcamHandler.videoReadingElement=videoTag;
|
|
9680
9815
|
//
|
|
9681
9816
|
//webcamHandler.localMediaStream=null;
|
|
9682
9817
|
//
|
|
@@ -9685,8 +9820,8 @@ function arrayFromString(strParam,compressResult=true,precisionFraction=null,isS
|
|
|
9685
9820
|
//
|
|
9686
9821
|
// // Not showing vendor prefixes or code that works cross-browser.
|
|
9687
9822
|
// var initStream=function(stream){
|
|
9688
|
-
// DEPRECATED : self.
|
|
9689
|
-
// self.
|
|
9823
|
+
// DEPRECATED : self.videoReadingElement.src=window.URL.createObjectURL(stream);
|
|
9824
|
+
// self.videoReadingElement.srcObject=stream;
|
|
9690
9825
|
// self.localMediaStream=stream;
|
|
9691
9826
|
// };
|
|
9692
9827
|
//
|
|
@@ -9757,7 +9892,7 @@ function arrayFromString(strParam,compressResult=true,precisionFraction=null,isS
|
|
|
9757
9892
|
//}
|
|
9758
9893
|
//
|
|
9759
9894
|
//webcamHandler.isReady=function(){
|
|
9760
|
-
// return webcamHandler.
|
|
9895
|
+
// return webcamHandler.videoReadingElement !== null;
|
|
9761
9896
|
//};
|
|
9762
9897
|
//
|
|
9763
9898
|
//return webcamHandler;
|
|
@@ -10838,6 +10973,49 @@ function normalizeDisplayQuotesForJSONParsing(str){
|
|
|
10838
10973
|
}
|
|
10839
10974
|
|
|
10840
10975
|
|
|
10976
|
+
|
|
10977
|
+
// Workaround to avoid «User interaction» errors for XR initialization :
|
|
10978
|
+
|
|
10979
|
+
function addUserInteractionButton(selfObject, functionToExecuteAfterParam, functionArguments, label="START"){
|
|
10980
|
+
|
|
10981
|
+
const userInteractionButtonId="userInteractionButton";
|
|
10982
|
+
let xrButton=document.getElementById(userInteractionButtonId);
|
|
10983
|
+
if(!xrButton){
|
|
10984
|
+
xrButton=document.createElement("button");
|
|
10985
|
+
xrButton.id=userInteractionButtonId;
|
|
10986
|
+
xrButton.innerHTML=label;
|
|
10987
|
+
xrButton.style="position:fixed; font-size:7em; width:100%; height:100%; z-index:9999; cursor:pointer;";
|
|
10988
|
+
document.body.appendChild(xrButton);
|
|
10989
|
+
}
|
|
10990
|
+
|
|
10991
|
+
xrButton.selfObject=selfObject;
|
|
10992
|
+
xrButton.listenerArgs=functionArguments;
|
|
10993
|
+
xrButton.functionToExecuteAfter=functionToExecuteAfterParam;
|
|
10994
|
+
xrButton.addEventListener("click",(event)=>{
|
|
10995
|
+
|
|
10996
|
+
const targetXRButton=event.target;
|
|
10997
|
+
const self=targetXRButton.selfObject;
|
|
10998
|
+
const listenerArgs=targetXRButton.listenerArgs;
|
|
10999
|
+
const functionToExecuteAfter=targetXRButton.functionToExecuteAfter;
|
|
11000
|
+
|
|
11001
|
+
targetXRButton.parentNode.removeChild(targetXRButton);
|
|
11002
|
+
|
|
11003
|
+
functionToExecuteAfter.apply(self,listenerArgs);
|
|
11004
|
+
|
|
11005
|
+
});
|
|
11006
|
+
|
|
11007
|
+
}
|
|
11008
|
+
|
|
11009
|
+
|
|
11010
|
+
|
|
11011
|
+
////
|
|
11012
|
+
|
|
11013
|
+
|
|
11014
|
+
|
|
11015
|
+
|
|
11016
|
+
|
|
11017
|
+
|
|
11018
|
+
|
|
10841
11019
|
//-------------------------------------------------------------------------------------------
|
|
10842
11020
|
|
|
10843
11021
|
|
|
@@ -10881,7 +11059,7 @@ function promptWindow(label,type=null,defaultValue=null,
|
|
|
10881
11059
|
//Each field rendering :
|
|
10882
11060
|
/* private */const getRenderedInputElement=function(inputType, defaultValueParam=null,/* OPTIONAL */labelParam=null){
|
|
10883
11061
|
|
|
10884
|
-
const
|
|
11062
|
+
const DISABLED_RADIO_OPACITY=0.6;
|
|
10885
11063
|
|
|
10886
11064
|
let inputElement=null;
|
|
10887
11065
|
if(contains(inputType, "password")){
|
|
@@ -10951,7 +11129,7 @@ function promptWindow(label,type=null,defaultValue=null,
|
|
|
10951
11129
|
|
|
10952
11130
|
if(choiceLabelStr.inactive){
|
|
10953
11131
|
radio.disabled=true;
|
|
10954
|
-
radio.style.opacity=
|
|
11132
|
+
radio.style.opacity=DISABLED_RADIO_OPACITY;
|
|
10955
11133
|
}
|
|
10956
11134
|
}
|
|
10957
11135
|
|
|
@@ -11332,155 +11510,7 @@ getInputCoords=function(event){
|
|
|
11332
11510
|
|
|
11333
11511
|
|
|
11334
11512
|
|
|
11335
|
-
|
|
11336
|
-
// Three.js utils :
|
|
11337
|
-
|
|
11338
|
-
/*private*/function isWebglAvailable(){
|
|
11339
|
-
try {
|
|
11340
|
-
let canvas=document.createElement("canvas");
|
|
11341
|
-
return !!(window.WebGLRenderingContext && (canvas.getContext("webgl") || canvas.getContext("experimental-webgl")));
|
|
11342
|
-
} catch (error){
|
|
11343
|
-
return false;
|
|
11344
|
-
}
|
|
11345
|
-
}
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
function getThreeRenderer(conf, pixelRatio=window.devicePixelRatio){
|
|
11349
|
-
|
|
11350
|
-
if(!THREE){
|
|
11351
|
-
lognow("ERROR : Three.js library missing ! Cannot create ThreeJS renderer.");
|
|
11352
|
-
return null;
|
|
11353
|
-
}
|
|
11354
|
-
|
|
11355
|
-
let renderer;
|
|
11356
|
-
if(conf.canvas){
|
|
11357
|
-
if(isWebglAvailable()){
|
|
11358
|
-
|
|
11359
|
-
if(conf.background==="transparent"){
|
|
11360
|
-
conf.alpha=true;
|
|
11361
|
-
}
|
|
11362
|
-
|
|
11363
|
-
renderer=new THREE.WebGLRenderer(conf);
|
|
11364
|
-
renderer.setPixelRatio(pixelRatio);
|
|
11365
|
-
|
|
11366
|
-
if(conf.background==="transparent"){
|
|
11367
|
-
renderer.setClearColor(0x000000, 0);
|
|
11368
|
-
}
|
|
11369
|
-
|
|
11370
|
-
}
|
|
11371
|
-
}else if(conf.type === "css"){
|
|
11372
|
-
renderer=new THREE.CSS3DRenderer();
|
|
11373
|
-
}
|
|
11374
|
-
|
|
11375
|
-
if(!renderer){
|
|
11376
|
-
// TRACE
|
|
11377
|
-
lognow("ERROR : No renderer found found. Aborting.");
|
|
11378
|
-
return null;
|
|
11379
|
-
}
|
|
11380
|
-
|
|
11381
|
-
// REMOVED FROM THREEJS :
|
|
11382
|
-
// let renderer=new THREE.CanvasRenderer({
|
|
11383
|
-
// canvas : conf.canvas
|
|
11384
|
-
// });
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
if(conf.canvas){
|
|
11388
|
-
renderer.setSize(conf.canvas.width, conf.canvas.height);
|
|
11389
|
-
}else if(conf.w && conf.h){
|
|
11390
|
-
renderer.setSize(conf.w, conf.h);
|
|
11391
|
-
}
|
|
11392
|
-
|
|
11393
|
-
return renderer;
|
|
11394
|
-
}
|
|
11395
|
-
|
|
11396
|
-
|
|
11397
|
-
function getVRHandler(renderer,modeVR="immersive-vr",optionsVR=["local-floor", "bounded-floor", "hand-tracking", "layers"]){
|
|
11398
|
-
// "immersive-ar", "immersive-vr", "inline"
|
|
11399
|
-
|
|
11400
|
-
// See : https://developer.mozilla.org/en-US/docs/Web/API/XRSystem/requestSession
|
|
11401
|
-
|
|
11402
|
-
if(typeof(navigator)===undefined || !renderer){
|
|
11403
|
-
// TRACE
|
|
11404
|
-
lognow("ERROR : No 3D renderer provided, cannot init the VR session.");
|
|
11405
|
-
return null;
|
|
11406
|
-
}
|
|
11407
|
-
|
|
11408
|
-
|
|
11409
|
-
if("xr" in navigator){
|
|
11410
|
-
|
|
11411
|
-
const result={
|
|
11412
|
-
|
|
11413
|
-
currentSession:null,
|
|
11414
|
-
|
|
11415
|
-
/*private*/onSessionStarted:async function(session){
|
|
11416
|
-
session.addEventListener("end", result.onSessionEnded);
|
|
11417
|
-
|
|
11418
|
-
await renderer.xr.setSession(session);
|
|
11419
|
-
|
|
11420
|
-
result.currentSession=session;
|
|
11421
|
-
},
|
|
11422
|
-
|
|
11423
|
-
/*private*/onSessionEnded:(event)=>{
|
|
11424
|
-
result.currentSession.removeEventListener("end", result.onSessionEnded);
|
|
11425
|
-
result.currentSession=null;
|
|
11426
|
-
},
|
|
11427
|
-
|
|
11428
|
-
start:()=>{
|
|
11429
|
-
|
|
11430
|
-
if(result.currentSession) return;
|
|
11431
|
-
|
|
11432
|
-
// WebXR's requestReferenceSpace only works if the corresponding feature
|
|
11433
|
-
// was requested at session creation time. For simplicity, just ask for
|
|
11434
|
-
// the interesting ones as optional features, but be aware that the
|
|
11435
|
-
// requestReferenceSpace call will fail if it turns out to be unavailable.
|
|
11436
|
-
// ('local' is always available for immersive sessions and doesn't need to
|
|
11437
|
-
// be requested separately.)
|
|
11438
|
-
|
|
11439
|
-
const sessionInitConf={optionalFeatures:optionsVR};
|
|
11440
|
-
navigator.xr.requestSession(modeVR, sessionInitConf)
|
|
11441
|
-
.then(result.onSessionStarted)
|
|
11442
|
-
.catch(error=>lognow("ERROR : Error initializing XR context : ",error));
|
|
11443
|
-
|
|
11444
|
-
return result;
|
|
11445
|
-
},
|
|
11446
|
-
|
|
11447
|
-
end:()=>{
|
|
11448
|
-
if(!result.currentSession) return;
|
|
11449
|
-
result.currentSession.end();
|
|
11450
|
-
return result;
|
|
11451
|
-
},
|
|
11452
|
-
|
|
11453
|
-
};
|
|
11454
|
-
|
|
11455
|
-
navigator.xr.isSessionSupported(modeVR).then((supported)=>{
|
|
11456
|
-
if(!supported){
|
|
11457
|
-
// TRACE
|
|
11458
|
-
lognow("ERROR : VR is not supported by your browser.");
|
|
11459
|
-
}else{
|
|
11460
|
-
result.isReady=true;
|
|
11461
|
-
}
|
|
11462
|
-
});
|
|
11463
|
-
|
|
11464
|
-
if(renderer.xr) renderer.xr.enabled=true;
|
|
11465
|
-
|
|
11466
|
-
return result;
|
|
11467
|
-
}
|
|
11468
|
-
|
|
11469
|
-
if(window.isSecureContext === false) {
|
|
11470
|
-
// TRACE
|
|
11471
|
-
lognow("ERROR : WEBXR needs a HTTPS environemnt.");
|
|
11472
|
-
return null;
|
|
11473
|
-
}
|
|
11474
|
-
|
|
11475
|
-
// TRACE
|
|
11476
|
-
lognow("ERROR : WEBXR not available.");
|
|
11477
|
-
|
|
11478
|
-
return null;
|
|
11479
|
-
};
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
// WEBGL Management :
|
|
11513
|
+
// HTML Management :
|
|
11484
11514
|
|
|
11485
11515
|
function convertHTMLToImage(elementHTML,callBack,mode="png",quality=null,height,width){
|
|
11486
11516
|
|
|
@@ -12570,6 +12600,10 @@ createOritaMicroClient=function(url, port, isNode=false, staticMicroClientIdPara
|
|
|
12570
12600
|
outputsGPIO:{},
|
|
12571
12601
|
inputsGPIO:{},
|
|
12572
12602
|
|
|
12603
|
+
setCaptureConfig:(captureConfig)=>{
|
|
12604
|
+
oritaClient.captureConfig=captureConfig;
|
|
12605
|
+
return oritaClient;
|
|
12606
|
+
},
|
|
12573
12607
|
|
|
12574
12608
|
};
|
|
12575
12609
|
|
|
@@ -12863,7 +12897,7 @@ createOritaMicroClient=function(url, port, isNode=false, staticMicroClientIdPara
|
|
|
12863
12897
|
console.log("mh:", mh); console.log("medias:", medias);
|
|
12864
12898
|
doOnStartMediaHandlerMicroClient(mh, medias, videoSide);
|
|
12865
12899
|
},
|
|
12866
|
-
(mh) => { mediaHandlerLocal = mh; });
|
|
12900
|
+
(mh) => { mediaHandlerLocal = mh; }).catch(err=>{lognow("ERROR : Could not get webcam handler for BROWSER MICROCLIENT.");});
|
|
12867
12901
|
|
|
12868
12902
|
} else { // Case node micro client :
|
|
12869
12903
|
|
|
@@ -12884,13 +12918,13 @@ createOritaMicroClient=function(url, port, isNode=false, staticMicroClientIdPara
|
|
|
12884
12918
|
console.log("audioConfigLocal", audioConfigLocal);
|
|
12885
12919
|
|
|
12886
12920
|
|
|
12887
|
-
mediaHandlerLocal =
|
|
12921
|
+
mediaHandlerLocal = getMediaHandler(
|
|
12888
12922
|
videoConfigLocal,
|
|
12889
12923
|
audioConfigLocal,
|
|
12890
12924
|
// CHANNELS_CONFIG,
|
|
12891
12925
|
{ width: captureWidth, height: captureHeight },
|
|
12892
12926
|
audioBufferSize, 1/*(means mono audio)*/,
|
|
12893
|
-
(mh) => { doOnStartMediaHandlerMicroClient(mh, medias, videoSide); });
|
|
12927
|
+
(mh) => { doOnStartMediaHandlerMicroClient(mh, medias, videoSide); }).catch(err=>{lognow("ERROR : Could not get webcam handler for MICROCLIENT.");});
|
|
12894
12928
|
|
|
12895
12929
|
|
|
12896
12930
|
}
|
|
@@ -13613,7 +13647,7 @@ getAORTACClient=function(clientId=getUUID(), serverNodeOrigin="ws://127.0.0.1:40
|
|
|
13613
13647
|
|
|
13614
13648
|
|
|
13615
13649
|
|
|
13616
|
-
/*utils GEOMETRY library associated with aotra version : «1_29072022-2359 (
|
|
13650
|
+
/*utils GEOMETRY library associated with aotra version : «1_29072022-2359 (11/11/2025-17:05:51)»*/
|
|
13617
13651
|
/*-----------------------------------------------------------------------------*/
|
|
13618
13652
|
|
|
13619
13653
|
|
|
@@ -13623,7 +13657,7 @@ getAORTACClient=function(clientId=getUUID(), serverNodeOrigin="ws://127.0.0.1:40
|
|
|
13623
13657
|
* Several authors of snippets published freely on the Internet contributed to this library.
|
|
13624
13658
|
* Feel free to use/modify-enhance/publish them under the terms of its license.
|
|
13625
13659
|
*
|
|
13626
|
-
* # Library name : «aotrautils»
|
|
13660
|
+
* # Library name : «aotrautils geometry»
|
|
13627
13661
|
* # Library license : HGPL(Help Burma) (see aotra README information for details : https://alqemia.com/aotra.js )
|
|
13628
13662
|
* # Author name : Jérémie Ratomposon (massively helped by his native country free education system)
|
|
13629
13663
|
* # Author email : info@alqemia.com
|
|
@@ -14852,7 +14886,10 @@ function rayVsUnitSphereClosestPoint(p, r) {
|
|
|
14852
14886
|
// MUST REMAIN AT THE END OF THIS LIBRARY FILE !
|
|
14853
14887
|
|
|
14854
14888
|
AOTRAUTILS_GEOMETRY_LIB_IS_LOADED=true;
|
|
14855
|
-
/*utils
|
|
14889
|
+
/*utils 3D library associated with aotra version : «1_29072022-2359 (11/11/2025-17:05:51)»*/
|
|
14890
|
+
/*-----------------------------------------------------------------------------*/
|
|
14891
|
+
|
|
14892
|
+
/*utils AI library associated with aotra version : «1_29072022-2359 (11/11/2025-17:05:51)»*/
|
|
14856
14893
|
/*-----------------------------------------------------------------------------*/
|
|
14857
14894
|
|
|
14858
14895
|
|
|
@@ -14998,7 +15035,7 @@ getOpenAIAPIClient=(modelName, apiURL, agentRole, defaultPrompt)=>{
|
|
|
14998
15035
|
|
|
14999
15036
|
|
|
15000
15037
|
|
|
15001
|
-
/*utils CONSOLE library associated with aotra version : «1_29072022-2359 (
|
|
15038
|
+
/*utils CONSOLE library associated with aotra version : «1_29072022-2359 (11/11/2025-17:05:51)»*/
|
|
15002
15039
|
/*-----------------------------------------------------------------------------*/
|
|
15003
15040
|
|
|
15004
15041
|
|
|
@@ -15422,7 +15459,12 @@ WebsocketImplementation={
|
|
|
15422
15459
|
return null;
|
|
15423
15460
|
}
|
|
15424
15461
|
|
|
15425
|
-
clientSocket=new WebSocket(serverURL+":"+port,/*WORKAROUND:*/{
|
|
15462
|
+
clientSocket=new WebSocket(serverURL+":"+port,/*WORKAROUND:*/{
|
|
15463
|
+
// CAUTION : SECURITY BREACH :
|
|
15464
|
+
// BUT ALSO NECESSARY TO ALLOW SELF-SIGNED CERTIFICATES USAGE WITH THE YESBOT SYSTEM !
|
|
15465
|
+
rejectUnauthorized:false, // (THIS IS A KNOWN SECURITY BREACH)
|
|
15466
|
+
secure: isSecure
|
|
15467
|
+
});
|
|
15426
15468
|
}else{
|
|
15427
15469
|
// NOW : socket.io :
|
|
15428
15470
|
//client on server-side:
|
|
@@ -15460,6 +15502,11 @@ WebsocketImplementation={
|
|
|
15460
15502
|
// BROWSER CLIENT MODE ONLY :
|
|
15461
15503
|
let clientSocket;
|
|
15462
15504
|
if(!WebsocketImplementation.useSocketIOImplementation){
|
|
15505
|
+
// CAUTION : PARAMETER rejectUnauthorized:false WILL DO NOTHING,
|
|
15506
|
+
// BECAUSE THIS IS COMPLETLY HANDLED BY THE BROWSER SECURITY POLICY !
|
|
15507
|
+
// SO TO CLEAR THE SSL ERROR :
|
|
15508
|
+
// - FIRST GO TO THE HTTPS:// SERVER ADDRESS WITH BROWSER
|
|
15509
|
+
// - THEN ADD THE SECURITY EXCEPTION IN THE BROWSER !
|
|
15463
15510
|
clientSocket=new WebSocket(serverURL+":"+port,["ws","wss"]);
|
|
15464
15511
|
}else if(typeof(io)!=="undefined"){
|
|
15465
15512
|
// OLD SYNTAX :clientSocket=io.connect(serverURL + ":" + port,{timeout: timeout, secure: isSecure});
|
|
@@ -15478,7 +15525,7 @@ WebsocketImplementation={
|
|
|
15478
15525
|
|
|
15479
15526
|
launchNodeHTTPServer=function(port, doOnConnect=null, doOnFinalizeServer=null, /*OPTIONAL*/sslOptions=null, httpHandlerParam=null, addCORSHeader=ADD_CORS_HEADER){
|
|
15480
15527
|
|
|
15481
|
-
const EXCLUDED_FILENAMES_PARTS=[".keyHash."];
|
|
15528
|
+
const EXCLUDED_FILENAMES_PARTS=[".keyHash.",".pem"];
|
|
15482
15529
|
|
|
15483
15530
|
|
|
15484
15531
|
|
|
@@ -15745,8 +15792,8 @@ initNodeServerInfrastructureWrapper=function(doOnClientConnection=null, doOnFina
|
|
|
15745
15792
|
}else{
|
|
15746
15793
|
try{
|
|
15747
15794
|
sslOptions={
|
|
15748
|
-
cert: fs.readFileSync(certPath),
|
|
15749
|
-
key: fs.readFileSync(keyPath),
|
|
15795
|
+
cert: fs.readFileSync(certPath, {encoding: "utf8"}),
|
|
15796
|
+
key: fs.readFileSync(keyPath, {encoding: "utf8"}),
|
|
15750
15797
|
};
|
|
15751
15798
|
}catch(exception){
|
|
15752
15799
|
// TRACE
|
|
@@ -17162,7 +17209,14 @@ class NodeServerInstance{
|
|
|
17162
17209
|
}
|
|
17163
17210
|
|
|
17164
17211
|
close(doOnCloseServer){
|
|
17165
|
-
if(!this.serverSocket)
|
|
17212
|
+
if(!this.serverSocket){
|
|
17213
|
+
//TRACE
|
|
17214
|
+
lognow("WARN : Server socket is null ! Cannot close an inexistant serer socket. Attempting to close attached HTTP server anyway.");
|
|
17215
|
+
lognow("WARN : THIS MAY CAUSE A MEMORY LEAK !!!");
|
|
17216
|
+
if(!this.listenableServer) return;
|
|
17217
|
+
this.listenableServer.close(doOnCloseServer);
|
|
17218
|
+
return;
|
|
17219
|
+
}
|
|
17166
17220
|
this.serverSocket.close(()=>{
|
|
17167
17221
|
if(!this.listenableServer) return;
|
|
17168
17222
|
this.listenableServer.close(doOnCloseServer);
|
aotrautils/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aotrautils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1797",
|
|
4
4
|
"main": "aotrautils.build.js",
|
|
5
5
|
"description": "A library for vanilla javascript utils (client-side) used in aotra javascript CMS",
|
|
6
6
|
"author": "Jeremie Ratomposon <info@alqemia.com> (https://alqemia.com)",
|