view release on metacpan or search on metacpan
lib/App/MHFS.pm view on Meta::CPAN
my %lookup = (
200 => "HTTP/1.1 200 OK\r\n",
206 => "HTTP/1.1 206 Partial Content\r\n",
301 => "HTTP/1.1 301 Moved Permanently\r\n",
307 => "HTTP/1.1 307 Temporary Redirect\r\n",
403 => "HTTP/1.1 403 Forbidden\r\n",
404 => "HTTP/1.1 404 File Not Found\r\n",
408 => "HTTP/1.1 408 Request Timeout\r\n",
416 => "HTTP/1.1 416 Range Not Satisfiable\r\n",
503 => "HTTP/1.1 503 Service Unavailable\r\n"
);
my $headtext = $lookup{$code};
if(!$headtext) {
say "_SendDataItem, bad code $code";
$self->Send403();
return;
}
lib/App/MHFS.pm view on Meta::CPAN
}
sub Send404 {
my ($self) = @_;
my $msg = "404 Not Found";
$self->SendHTML($msg, {'code' => 404});
}
sub Send408 {
my ($self) = @_;
my $msg = "408 Request Timeout";
$self->{'outheaders'}{'Connection'} = 'close';
$self->SendHTML($msg, {'code' => 408});
}
sub Send416 {
my ($self, $cursize) = @_;
$self->{'outheaders'}{'Content-Range'} = "*/$cursize";
$self->SendHTML('', {'code' => 416});
}
share/public_html/static/hls.js view on Meta::CPAN
retryDelay = void 0,
maxRetryDelay = void 0;
// apply different configs for retries depending on
// context (manifest, level, audio/subs playlist)
switch (context.type) {
case ContextType.MANIFEST:
maxRetry = config.manifestLoadingMaxRetry;
timeout = config.manifestLoadingTimeOut;
retryDelay = config.manifestLoadingRetryDelay;
maxRetryDelay = config.manifestLoadingMaxRetryTimeout;
break;
case ContextType.LEVEL:
// Disable internal loader retry logic, since we are managing retries in Level Controller
maxRetry = 0;
timeout = config.levelLoadingTimeOut;
// TODO Introduce retry settings for audio-track and subtitle-track, it should not use level retry config
break;
default:
maxRetry = config.levelLoadingMaxRetry;
timeout = config.levelLoadingTimeOut;
retryDelay = config.levelLoadingRetryDelay;
maxRetryDelay = config.levelLoadingMaxRetryTimeout;
break;
}
loader = this.createInternalLoader(context);
context.url = url;
context.responseType = context.responseType || ''; // FIXME: (should not be necessary to do this)
var loaderConfig = {
timeout: timeout,
maxRetry: maxRetry,
retryDelay: retryDelay,
maxRetryDelay: maxRetryDelay
};
var loaderCallbacks = {
onSuccess: this.loadsuccess.bind(this),
onError: this.loaderror.bind(this),
onTimeout: this.loadtimeout.bind(this)
};
logger["b" /* logger */].debug('Calling internal loader delegate for URL: ' + url);
loader.load(context, loaderConfig, loaderCallbacks);
return true;
};
PlaylistLoader.prototype.loadsuccess = function loadsuccess(response, stats, context) {
share/public_html/static/hls.js view on Meta::CPAN
if (!isNaN(start) && !isNaN(end)) {
loaderContext.rangeStart = start;
loaderContext.rangeEnd = end;
}
loaderConfig = {
timeout: config.fragLoadingTimeOut,
maxRetry: 0,
retryDelay: 0,
maxRetryDelay: config.fragLoadingMaxRetryTimeout
};
loaderCallbacks = {
onSuccess: this.loadsuccess.bind(this),
onError: this.loaderror.bind(this),
onTimeout: this.loadtimeout.bind(this),
onProgress: this.loadprogress.bind(this)
};
loader.load(loaderContext, loaderConfig, loaderCallbacks);
};
FragmentLoader.prototype.loadsuccess = function loadsuccess(response, stats, context) {
var networkDetails = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
var payload = response.data,
share/public_html/static/hls.js view on Meta::CPAN
loader.abort();
}
frag.loader = this.loaders[type] = new config.loader(config);
this.decrypturl = uri;
this.decryptkey = null;
var loaderContext = void 0,
loaderConfig = void 0,
loaderCallbacks = void 0;
loaderContext = { url: uri, frag: frag, responseType: 'arraybuffer' };
loaderConfig = { timeout: config.fragLoadingTimeOut, maxRetry: config.fragLoadingMaxRetry, retryDelay: config.fragLoadingRetryDelay, maxRetryDelay: config.fragLoadingMaxRetryTimeout };
loaderCallbacks = { onSuccess: this.loadsuccess.bind(this), onError: this.loaderror.bind(this), onTimeout: this.loadtimeout.bind(this) };
frag.loader.load(loaderContext, loaderConfig, loaderCallbacks);
} else if (this.decryptkey) {
// we already loaded this key, return it
decryptdata.key = this.decryptkey;
this.hls.trigger(events["a" /* default */].KEY_LOADED, { frag: frag });
}
};
KeyLoader.prototype.loadsuccess = function loadsuccess(response, stats, context) {
var frag = context.frag;
share/public_html/static/hls.js view on Meta::CPAN
return false;
});
/**
* @returns {boolean} True when timeout was cleared, false when none was set (no effect)
*/
TaskLoop.prototype.clearNextTick = function clearNextTick() {
if (this._tickTimer) {
clearTimeout(this._tickTimer);
this._tickTimer = null;
return true;
}
return false;
};
/**
* Will call the subclass doTick implementation in this main loop tick
* or in the next one (via setTimeout(,0)) in case it has already been called
* in this tick (in case this is a re-entrant call).
*/
TaskLoop.prototype.tick = function tick() {
this._tickCallCount++;
if (this._tickCallCount === 1) {
this.doTick();
// re-entrant call to tick from previous doTick call stack
// -> schedule a call on the next main loop iteration to process this task processing request
if (this._tickCallCount > 1) {
// make sure only one timer exists at any time at max
this.clearNextTick();
this._tickTimer = setTimeout(this._boundTick, 0);
}
this._tickCallCount = 0;
}
};
/**
* For subclass to implement task logic
* @abstract
*/
share/public_html/static/hls.js view on Meta::CPAN
var mediaBuffered = !!this.media && BufferHelper.isBuffered(this.media, this.media.currentTime) && BufferHelper.isBuffered(this.media, this.media.currentTime + 0.5);
switch (data.details) {
case errors["a" /* ErrorDetails */].FRAG_LOAD_ERROR:
case errors["a" /* ErrorDetails */].FRAG_LOAD_TIMEOUT:
case errors["a" /* ErrorDetails */].KEY_LOAD_ERROR:
case errors["a" /* ErrorDetails */].KEY_LOAD_TIMEOUT:
if (!data.fatal) {
// keep retrying until the limit will be reached
if (this.fragLoadError + 1 <= this.config.fragLoadingMaxRetry) {
// exponential backoff capped to config.fragLoadingMaxRetryTimeout
var delay = Math.min(Math.pow(2, this.fragLoadError) * this.config.fragLoadingRetryDelay, this.config.fragLoadingMaxRetryTimeout);
logger["b" /* logger */].warn('mediaController: frag loading failed, retry in ' + delay + ' ms');
this.retryDate = window.performance.now() + delay;
// retry loading state
// if loadedmetadata is not set, it means that we are emergency switch down on first frag
// in that case, reset startFragRequested flag
if (!this.loadedmetadata) {
this.startFragRequested = false;
this.nextLoadPosition = this.startPosition;
}
this.fragLoadError++;
share/public_html/static/hls.js view on Meta::CPAN
return _this;
}
LevelController.prototype.onHandlerDestroying = function onHandlerDestroying() {
this.clearTimer();
this.manualLevelIndex = -1;
};
LevelController.prototype.clearTimer = function clearTimer() {
if (this.timer !== null) {
clearTimeout(this.timer);
this.timer = null;
}
};
LevelController.prototype.startLoad = function startLoad() {
var levels = this._levels;
this.canload = true;
this.levelRetryCount = 0;
share/public_html/static/hls.js view on Meta::CPAN
var redundantLevels = void 0,
delay = void 0,
nextLevel = void 0;
level.loadError++;
level.fragmentError = fragmentError;
if (levelError) {
if (this.levelRetryCount + 1 <= config.levelLoadingMaxRetry) {
// exponential backoff capped to max retry timeout
delay = Math.min(Math.pow(2, this.levelRetryCount) * config.levelLoadingRetryDelay, config.levelLoadingMaxRetryTimeout);
// Schedule level reload
this.timer = setTimeout(function () {
return _this2.loadLevel();
}, delay);
// boolean used to inform stream controller not to switch back to IDLE on non fatal error
errorEvent.levelRetry = true;
this.levelRetryCount++;
logger["b" /* logger */].warn('level controller, ' + errorDetails + ', retry in ' + delay + ' ms, current retry count is ' + this.levelRetryCount);
} else {
logger["b" /* logger */].error('level controller, cannot recover from ' + errorDetails + ' error');
this.currentLevelIndex = null;
// stopping live reloading timer if any
share/public_html/static/hls.js view on Meta::CPAN
// changed then it MUST wait for a period of one-half the target
// duration before retrying.
reloadInterval /= 2;
logger["b" /* logger */].log('same live playlist, reload twice faster');
}
// decrement reloadInterval with level loading delay
reloadInterval -= level_controller_performance.now() - data.stats.trequest;
// in any case, don't reload more than half of target duration
reloadInterval = Math.max(targetdurationMs / 2, Math.round(reloadInterval));
logger["b" /* logger */].log('live playlist, reload in ' + Math.round(reloadInterval) + ' ms');
this.timer = setTimeout(function () {
return _this3.loadLevel();
}, reloadInterval);
} else {
this.clearTimer();
}
};
LevelController.prototype.onAudioTrackSwitched = function onAudioTrackSwitched(data) {
var audioGroupId = this.hls.audioTracks[data.id].groupId;
share/public_html/static/hls.js view on Meta::CPAN
this.loader = null;
};
XhrLoader.prototype.abort = function abort() {
var loader = this.loader;
if (loader && loader.readyState !== 4) {
this.stats.aborted = true;
loader.abort();
}
window.clearTimeout(this.requestTimeout);
this.requestTimeout = null;
window.clearTimeout(this.retryTimeout);
this.retryTimeout = null;
};
XhrLoader.prototype.load = function load(context, config, callbacks) {
this.context = context;
this.config = config;
this.callbacks = callbacks;
this.stats = { trequest: xhr_loader_performance.now(), retry: 0 };
this.retryDelay = config.retryDelay;
this.loadInternal();
};
share/public_html/static/hls.js view on Meta::CPAN
if (context.rangeEnd) {
xhr.setRequestHeader('Range', 'bytes=' + context.rangeStart + '-' + (context.rangeEnd - 1));
}
xhr.onreadystatechange = this.readystatechange.bind(this);
xhr.onprogress = this.loadprogress.bind(this);
xhr.responseType = context.responseType;
// setup timeout before we perform request
this.requestTimeout = window.setTimeout(this.loadtimeout.bind(this), this.config.timeout);
xhr.send();
};
XhrLoader.prototype.readystatechange = function readystatechange(event) {
var xhr = event.currentTarget,
readyState = xhr.readyState,
stats = this.stats,
context = this.context,
config = this.config;
// don't proceed if xhr has been aborted
if (stats.aborted) {
return;
}
// >= HEADERS_RECEIVED
if (readyState >= 2) {
// clear xhr timeout and rearm it if readyState less than 4
window.clearTimeout(this.requestTimeout);
if (stats.tfirst === 0) {
stats.tfirst = Math.max(xhr_loader_performance.now(), stats.trequest);
}
if (readyState === 4) {
var status = xhr.status;
// http status between 200 to 299 are all successful
if (status >= 200 && status < 300) {
stats.tload = Math.max(stats.tfirst, xhr_loader_performance.now());
var data = void 0,
share/public_html/static/hls.js view on Meta::CPAN
// if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
if (stats.retry >= config.maxRetry || status >= 400 && status < 499) {
logger["b" /* logger */].error(status + ' while loading ' + context.url);
this.callbacks.onError({ code: status, text: xhr.statusText }, context, xhr);
} else {
// retry
logger["b" /* logger */].warn(status + ' while loading ' + context.url + ', retrying in ' + this.retryDelay + '...');
// aborts and resets internal state
this.destroy();
// schedule retry
this.retryTimeout = window.setTimeout(this.loadInternal.bind(this), this.retryDelay);
// set exponential backoff
this.retryDelay = Math.min(2 * this.retryDelay, config.maxRetryDelay);
stats.retry++;
}
}
} else {
// readyState >= 2 AND readyState !==4 (readyState = HEADERS_RECEIVED || LOADING) rearm timeout as xhr not finished yet
this.requestTimeout = window.setTimeout(this.loadtimeout.bind(this), config.timeout);
}
}
};
XhrLoader.prototype.loadtimeout = function loadtimeout() {
logger["b" /* logger */].warn('timeout while loading ' + this.context.url);
this.callbacks.onTimeout(this.stats, this.context, null);
};
XhrLoader.prototype.loadprogress = function loadprogress(event) {
var xhr = event.currentTarget,
stats = this.stats;
stats.loaded = event.loaded;
if (event.lengthComputable) {
stats.total = event.total;
}
share/public_html/static/hls.js view on Meta::CPAN
var loadError = this.fragLoadError;
if (loadError) {
loadError++;
} else {
loadError = 1;
}
var config = this.config;
if (loadError <= config.fragLoadingMaxRetry) {
this.fragLoadError = loadError;
// exponential backoff capped to config.fragLoadingMaxRetryTimeout
var delay = Math.min(Math.pow(2, loadError - 1) * config.fragLoadingRetryDelay, config.fragLoadingMaxRetryTimeout);
logger["b" /* logger */].warn('AudioStreamController: frag loading failed, retry in ' + delay + ' ms');
this.retryDate = audio_stream_controller_performance.now() + delay;
// retry loading state
this.state = audio_stream_controller_State.FRAG_LOADING_WAITING_RETRY;
} else {
logger["b" /* logger */].error('AudioStreamController: ' + data.details + ' reaches max retry, redispatch as fatal ...');
// switch error to fatal
data.fatal = true;
this.state = audio_stream_controller_State.ERROR;
}
share/public_html/static/hls.js view on Meta::CPAN
liveMaxLatencyDurationCount: Infinity, // used by stream-controller
liveSyncDuration: undefined, // used by stream-controller
liveMaxLatencyDuration: undefined, // used by stream-controller
liveDurationInfinity: false, // used by buffer-controller
maxMaxBufferLength: 600, // used by stream-controller
enableWorker: true, // used by demuxer
enableSoftwareAES: true, // used by decrypter
manifestLoadingTimeOut: 10000, // used by playlist-loader
manifestLoadingMaxRetry: 1, // used by playlist-loader
manifestLoadingRetryDelay: 1000, // used by playlist-loader
manifestLoadingMaxRetryTimeout: 64000, // used by playlist-loader
startLevel: undefined, // used by level-controller
levelLoadingTimeOut: 10000, // used by playlist-loader
levelLoadingMaxRetry: 4, // used by playlist-loader
levelLoadingRetryDelay: 1000, // used by playlist-loader
levelLoadingMaxRetryTimeout: 64000, // used by playlist-loader
fragLoadingTimeOut: 20000, // used by fragment-loader
fragLoadingMaxRetry: 6, // used by fragment-loader
fragLoadingRetryDelay: 1000, // used by fragment-loader
fragLoadingMaxRetryTimeout: 64000, // used by fragment-loader
startFragPrefetch: false, // used by stream-controller
fpsDroppedMonitoringPeriod: 5000, // used by fps-controller
fpsDroppedMonitoringThreshold: 0.2, // used by fps-controller
appendErrorMaxRetry: 3, // used by buffer-controller
loader: xhr_loader,
// loader: FetchLoader,
fLoader: undefined, // used by fragment-loader
pLoader: undefined, // used by playlist-loader
xhrSetup: undefined, // used by xhr-loader
licenseXhrSetup: undefined, // used by eme-controller
share/public_html/static/jsmpeg.min.js view on Meta::CPAN
var JSMpeg={Player:null,VideoElement:null,BitBuffer:null,Source:{},Demuxer:{},Decoder:{},Renderer:{},AudioOutput:{},Now:function(){return window.performance?window.performance.now()/1e3:Date.now()/1e3},CreateVideoElements:function(){var elements=docu...
src++;y|=sY[src]<<16;src++;y|=sY[src]<<24;src++;dY[dest++]=y}dest+=scan>>2;src+=scan}}}width=this.halfWidth;scan=width-8;H=motionH/2>>1;V=motionV/2>>1;oddH=(motionH/2&1)===1;oddV=(motionV/2&1)===1;src=((this.mbRow<<3)+V)*width+(this.mbCol<<3)+H;dest=...
gl.uniform1i(gl.getUniformLocation(this.program,name),index);return texture};WebGLRenderer.prototype.createProgram=function(vsh,fsh){var gl=this.gl;var program=gl.createProgram();gl.attachShader(program,this.compileShader(gl.VERTEX_SHADER,vsh));gl.at...
share/public_html/static/music_inc/drflac.js view on Meta::CPAN
var Module = (() => {
var _scriptName = import.meta.url;
return (
async function(moduleArg = {}) {
var moduleRtn;
var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});["_network_drflac_open_mem","_network_drflac_read_pcm_frames_f32_mem","_network_dr...
return moduleRtn;
}
);
})();
export default Module;
share/public_html/static/music_inc/music_drflac_module.cache.js view on Meta::CPAN
let DrFlac = {
'drflac' : true,
'ready' : false,
'on' : function(event, cb) {
if(event === 'ready') {
this.on_ready = cb;
}
}
};
const sleep = m => new Promise(r => setTimeout(r, m));
const waitForEvent = (obj, event) => {
return new Promise(function(resolve) {
obj.on(event, function() {
resolve();
});
});
};
class Mutex {
share/public_html/static/music_inc/music_inc_module.js view on Meta::CPAN
AudioQueue[i].source.stop();
}
console.log('aqid: ' + AudioQueue[i].aqid + ' AQ_stopAudioWithoutID delete, curr: ' + aqid);
}
if(dCount) {
AudioQueue.splice(AudioQueue.length - dCount, dCount);
}
}
if(typeof abortablesleep === 'undefined') {
//const sleep = m => new Promise(r => setTimeout(r, m));
const abortablesleep = (ms, signal) => new Promise(function(resolve) {
const onTimerDone = function() {
resolve();
signal.removeEventListener('abort', stoptimer);
};
let timer = setTimeout(function() {
console.log('sleep done ' + ms);
onTimerDone();
}, ms);
const stoptimer = function() {
console.log('aborted sleep');
onTimerDone();
clearTimeout(timer);
};
signal.addEventListener('abort', stoptimer);
});
DeclareGlobalFunc('abortablesleep', abortablesleep);
}
let FAQ_MUTEX = new Mutex();
async function fillAudioQueue(time) {
// starting a fresh queue, render the text
if(Tracks_QueueCurrent) {
share/public_html/static/music_inc/music_inc_module.js view on Meta::CPAN
PTrackUrlParams.append('ptrack', track.trackname);
});
*/
for(let track = Tracks_HEAD; track; track = track.next) {
PTrackUrlParams.append('ptrack', track.trackname);
}
}
function BuildPTrack() {
// window.history.replaceState is slow :(
setTimeout(function() {
_BuildPTrack();
var urlstring = PTrackUrlParams.toString();
if (urlstring != '') {
console.log('replace state begin');
window.history.replaceState('playlist', 'Title', '?' + urlstring);
console.log('replace state end');
}
}, 1000);
}
share/public_html/static/music_inc/src/miniaudio.h view on Meta::CPAN
case MA_BAD_ADDRESS: return "Bad address";
case MA_BAD_SEEK: return "Illegal seek";
case MA_BAD_PIPE: return "Broken pipe";
case MA_DEADLOCK: return "Deadlock";
case MA_TOO_MANY_LINKS: return "Too many links";
case MA_NOT_IMPLEMENTED: return "Not implemented";
case MA_NO_MESSAGE: return "No message of desired type";
case MA_BAD_MESSAGE: return "Invalid message";
case MA_NO_DATA_AVAILABLE: return "No data available";
case MA_INVALID_DATA: return "Invalid data";
case MA_TIMEOUT: return "Timeout";
case MA_NO_NETWORK: return "Network unavailable";
case MA_NOT_UNIQUE: return "Not unique";
case MA_NOT_SOCKET: return "Socket operation on non-socket";
case MA_NO_ADDRESS: return "Destination address required";
case MA_BAD_PROTOCOL: return "Protocol wrong type for socket";
case MA_PROTOCOL_UNAVAILABLE: return "Protocol not available";
case MA_PROTOCOL_NOT_SUPPORTED: return "Protocol not supported";
case MA_PROTOCOL_FAMILY_NOT_SUPPORTED: return "Protocol family not supported";
case MA_ADDRESS_FAMILY_NOT_SUPPORTED: return "Address family not supported";
case MA_SOCKET_NOT_SUPPORTED: return "Socket type not supported";
share/public_html/static/music_worklet_inprogress/decoder/bin/_mhfscl.js view on Meta::CPAN
var Module = (() => {
var _scriptName = import.meta.url;
return (
async function(moduleArg = {}) {
var moduleRtn;
var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof im...
return moduleRtn;
}
);
})();
export default Module;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
case MA_BAD_ADDRESS: return "Bad address";
case MA_BAD_SEEK: return "Illegal seek";
case MA_BAD_PIPE: return "Broken pipe";
case MA_DEADLOCK: return "Deadlock";
case MA_TOO_MANY_LINKS: return "Too many links";
case MA_NOT_IMPLEMENTED: return "Not implemented";
case MA_NO_MESSAGE: return "No message of desired type";
case MA_BAD_MESSAGE: return "Invalid message";
case MA_NO_DATA_AVAILABLE: return "No data available";
case MA_INVALID_DATA: return "Invalid data";
case MA_TIMEOUT: return "Timeout";
case MA_NO_NETWORK: return "Network unavailable";
case MA_NOT_UNIQUE: return "Not unique";
case MA_NOT_SOCKET: return "Socket operation on non-socket";
case MA_NO_ADDRESS: return "Destination address required";
case MA_BAD_PROTOCOL: return "Protocol wrong type for socket";
case MA_PROTOCOL_UNAVAILABLE: return "Protocol not available";
case MA_PROTOCOL_NOT_SUPPORTED: return "Protocol not supported";
case MA_PROTOCOL_FAMILY_NOT_SUPPORTED: return "Protocol family not supported";
case MA_ADDRESS_FAMILY_NOT_SUPPORTED: return "Address family not supported";
case MA_SOCKET_NOT_SUPPORTED: return "Socket type not supported";
share/public_html/static/music_worklet_inprogress/decoder/mhfscl.js view on Meta::CPAN
let MHFSCL = {
'mhfscl' : true,
'ready' : false,
'on' : function(event, cb) {
if(event === 'ready') {
this.on_ready = cb;
}
}
};
const sleep = m => new Promise(r => setTimeout(r, m));
const waitForEvent = (obj, event) => {
return new Promise(function(resolve) {
obj.on(event, function() {
resolve();
});
});
};
class Mutex {
share/public_html/static/music_worklet_inprogress/music_inc_module.js view on Meta::CPAN
PTrackUrlParams.append('ptrack', track.md.trackname);
});
for(let track = MHFSPLAYER.Tracks_HEAD; track; track = track.next) {
PTrackUrlParams.append('ptrack', track.md.trackname);
}
}
const BuildPTrack = function() {
// window.history.replaceState is slow :(
setTimeout(function() {
_BuildPTrack();
var urlstring = PTrackUrlParams.toString();
if (urlstring != '') {
console.log('replace state begin');
//window.history hangs the page
//window.history.replaceState('playlist', 'Title', '?' + urlstring);
console.log('replace state end');
}
}, 5000);
}
share/public_html/static/music_worklet_inprogress/player/mhfsplayer.js view on Meta::CPAN
this._locking = this._locking.then(() => willLock);
return willUnlock;
}
}
const abortablesleep = (ms, signal) => new Promise(function(resolve) {
const onTimerDone = function() {
resolve();
signal.removeEventListener('abort', stoptimer);
};
let timer = setTimeout(function() {
//console.log('sleep done ' + ms);
onTimerDone();
}, ms);
const stoptimer = function() {
console.log('aborted sleep');
onTimerDone();
clearTimeout(timer);
};
signal.addEventListener('abort', stoptimer);
});
const abortablesleep_status = async function (ms, signal) {
await abortablesleep(ms, signal);
if(signal.aborted) {
return false;
}
return true;