livekit-client 1.9.4 → 1.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/livekit-client.esm.mjs +864 -1537
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts +1 -2
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +1 -0
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +0 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/src/utils/AsyncQueue.d.ts.map +1 -0
- package/dist/src/utils/browserParser.d.ts +10 -0
- package/dist/src/utils/browserParser.d.ts.map +1 -0
- package/dist/ts4.2/src/api/SignalClient.d.ts +1 -2
- package/dist/ts4.2/src/room/Room.d.ts +1 -0
- package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +0 -1
- package/dist/ts4.2/src/utils/browserParser.d.ts +10 -0
- package/package.json +6 -4
- package/src/api/SignalClient.ts +1 -2
- package/src/room/Room.ts +5 -2
- package/src/room/participant/LocalParticipant.ts +0 -1
- package/src/room/utils.ts +17 -16
- package/src/{AsyncQueue.test.ts → utils/AsyncQueue.test.ts} +1 -1
- package/src/{AsyncQueue.ts → utils/AsyncQueue.ts} +1 -1
- package/src/utils/browserParser.test.ts +58 -0
- package/src/utils/browserParser.ts +72 -0
- package/dist/src/AsyncQueue.d.ts.map +0 -1
- /package/dist/src/{AsyncQueue.d.ts → utils/AsyncQueue.d.ts} +0 -0
- /package/dist/ts4.2/src/{AsyncQueue.d.ts → utils/AsyncQueue.d.ts} +0 -0
@@ -10090,1332 +10090,110 @@ adapterFactory({
|
|
10090
10090
|
window: typeof window === 'undefined' ? undefined : window
|
10091
10091
|
});
|
10092
10092
|
|
10093
|
-
|
10094
|
-
|
10095
|
-
(function (
|
10096
|
-
|
10097
|
-
|
10098
|
-
|
10099
|
-
|
10100
|
-
|
10101
|
-
|
10102
|
-
|
10103
|
-
|
10104
|
-
|
10105
|
-
|
10106
|
-
|
10107
|
-
|
10108
|
-
|
10109
|
-
|
10110
|
-
|
10111
|
-
|
10112
|
-
EMPTY = '',
|
10113
|
-
UNKNOWN = '?',
|
10114
|
-
FUNC_TYPE = 'function',
|
10115
|
-
UNDEF_TYPE = 'undefined',
|
10116
|
-
OBJ_TYPE = 'object',
|
10117
|
-
STR_TYPE = 'string',
|
10118
|
-
MAJOR = 'major',
|
10119
|
-
MODEL = 'model',
|
10120
|
-
NAME = 'name',
|
10121
|
-
TYPE = 'type',
|
10122
|
-
VENDOR = 'vendor',
|
10123
|
-
VERSION = 'version',
|
10124
|
-
ARCHITECTURE = 'architecture',
|
10125
|
-
CONSOLE = 'console',
|
10126
|
-
MOBILE = 'mobile',
|
10127
|
-
TABLET = 'tablet',
|
10128
|
-
SMARTTV = 'smarttv',
|
10129
|
-
WEARABLE = 'wearable',
|
10130
|
-
EMBEDDED = 'embedded',
|
10131
|
-
UA_MAX_LENGTH = 350;
|
10132
|
-
var AMAZON = 'Amazon',
|
10133
|
-
APPLE = 'Apple',
|
10134
|
-
ASUS = 'ASUS',
|
10135
|
-
BLACKBERRY = 'BlackBerry',
|
10136
|
-
BROWSER = 'Browser',
|
10137
|
-
CHROME = 'Chrome',
|
10138
|
-
EDGE = 'Edge',
|
10139
|
-
FIREFOX = 'Firefox',
|
10140
|
-
GOOGLE = 'Google',
|
10141
|
-
HUAWEI = 'Huawei',
|
10142
|
-
LG = 'LG',
|
10143
|
-
MICROSOFT = 'Microsoft',
|
10144
|
-
MOTOROLA = 'Motorola',
|
10145
|
-
OPERA = 'Opera',
|
10146
|
-
SAMSUNG = 'Samsung',
|
10147
|
-
SHARP = 'Sharp',
|
10148
|
-
SONY = 'Sony',
|
10149
|
-
XIAOMI = 'Xiaomi',
|
10150
|
-
ZEBRA = 'Zebra',
|
10151
|
-
FACEBOOK = 'Facebook',
|
10152
|
-
CHROMIUM_OS = 'Chromium OS',
|
10153
|
-
MAC_OS = 'Mac OS';
|
10154
|
-
|
10155
|
-
///////////
|
10156
|
-
// Helper
|
10157
|
-
//////////
|
10158
|
-
|
10159
|
-
var extend = function (regexes, extensions) {
|
10160
|
-
var mergedRegexes = {};
|
10161
|
-
for (var i in regexes) {
|
10162
|
-
if (extensions[i] && extensions[i].length % 2 === 0) {
|
10163
|
-
mergedRegexes[i] = extensions[i].concat(regexes[i]);
|
10164
|
-
} else {
|
10165
|
-
mergedRegexes[i] = regexes[i];
|
10166
|
-
}
|
10167
|
-
}
|
10168
|
-
return mergedRegexes;
|
10169
|
-
},
|
10170
|
-
enumerize = function (arr) {
|
10171
|
-
var enums = {};
|
10172
|
-
for (var i = 0; i < arr.length; i++) {
|
10173
|
-
enums[arr[i].toUpperCase()] = arr[i];
|
10174
|
-
}
|
10175
|
-
return enums;
|
10176
|
-
},
|
10177
|
-
has = function (str1, str2) {
|
10178
|
-
return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
|
10179
|
-
},
|
10180
|
-
lowerize = function (str) {
|
10181
|
-
return str.toLowerCase();
|
10182
|
-
},
|
10183
|
-
majorize = function (version) {
|
10184
|
-
return typeof version === STR_TYPE ? version.replace(/[^\d\.]/g, EMPTY).split('.')[0] : undefined$1;
|
10185
|
-
},
|
10186
|
-
trim = function (str, len) {
|
10187
|
-
if (typeof str === STR_TYPE) {
|
10188
|
-
str = str.replace(/^\s\s*/, EMPTY);
|
10189
|
-
return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
|
10190
|
-
}
|
10191
|
-
};
|
10192
|
-
|
10193
|
-
///////////////
|
10194
|
-
// Map helper
|
10195
|
-
//////////////
|
10196
|
-
|
10197
|
-
var rgxMapper = function (ua, arrays) {
|
10198
|
-
var i = 0,
|
10199
|
-
j,
|
10200
|
-
k,
|
10201
|
-
p,
|
10202
|
-
q,
|
10203
|
-
matches,
|
10204
|
-
match;
|
10205
|
-
|
10206
|
-
// loop through all regexes maps
|
10207
|
-
while (i < arrays.length && !matches) {
|
10208
|
-
var regex = arrays[i],
|
10209
|
-
// even sequence (0,2,4,..)
|
10210
|
-
props = arrays[i + 1]; // odd sequence (1,3,5,..)
|
10211
|
-
j = k = 0;
|
10212
|
-
|
10213
|
-
// try matching uastring with regexes
|
10214
|
-
while (j < regex.length && !matches) {
|
10215
|
-
if (!regex[j]) {
|
10216
|
-
break;
|
10217
|
-
}
|
10218
|
-
matches = regex[j++].exec(ua);
|
10219
|
-
if (!!matches) {
|
10220
|
-
for (p = 0; p < props.length; p++) {
|
10221
|
-
match = matches[++k];
|
10222
|
-
q = props[p];
|
10223
|
-
// check if given property is actually array
|
10224
|
-
if (typeof q === OBJ_TYPE && q.length > 0) {
|
10225
|
-
if (q.length === 2) {
|
10226
|
-
if (typeof q[1] == FUNC_TYPE) {
|
10227
|
-
// assign modified match
|
10228
|
-
this[q[0]] = q[1].call(this, match);
|
10229
|
-
} else {
|
10230
|
-
// assign given value, ignore regex match
|
10231
|
-
this[q[0]] = q[1];
|
10232
|
-
}
|
10233
|
-
} else if (q.length === 3) {
|
10234
|
-
// check whether function or regex
|
10235
|
-
if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
|
10236
|
-
// call function (usually string mapper)
|
10237
|
-
this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined$1;
|
10238
|
-
} else {
|
10239
|
-
// sanitize match using given regex
|
10240
|
-
this[q[0]] = match ? match.replace(q[1], q[2]) : undefined$1;
|
10241
|
-
}
|
10242
|
-
} else if (q.length === 4) {
|
10243
|
-
this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined$1;
|
10244
|
-
}
|
10245
|
-
} else {
|
10246
|
-
this[q] = match ? match : undefined$1;
|
10247
|
-
}
|
10248
|
-
}
|
10249
|
-
}
|
10250
|
-
}
|
10251
|
-
i += 2;
|
10252
|
-
}
|
10253
|
-
},
|
10254
|
-
strMapper = function (str, map) {
|
10255
|
-
for (var i in map) {
|
10256
|
-
// check if current value is array
|
10257
|
-
if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
|
10258
|
-
for (var j = 0; j < map[i].length; j++) {
|
10259
|
-
if (has(map[i][j], str)) {
|
10260
|
-
return i === UNKNOWN ? undefined$1 : i;
|
10261
|
-
}
|
10262
|
-
}
|
10263
|
-
} else if (has(map[i], str)) {
|
10264
|
-
return i === UNKNOWN ? undefined$1 : i;
|
10265
|
-
}
|
10266
|
-
}
|
10267
|
-
return str;
|
10268
|
-
};
|
10269
|
-
|
10270
|
-
///////////////
|
10271
|
-
// String map
|
10272
|
-
//////////////
|
10273
|
-
|
10274
|
-
// Safari < 3.0
|
10275
|
-
var oldSafariMap = {
|
10276
|
-
'1.0': '/8',
|
10277
|
-
'1.2': '/1',
|
10278
|
-
'1.3': '/3',
|
10279
|
-
'2.0': '/412',
|
10280
|
-
'2.0.2': '/416',
|
10281
|
-
'2.0.3': '/417',
|
10282
|
-
'2.0.4': '/419',
|
10283
|
-
'?': '/'
|
10284
|
-
},
|
10285
|
-
windowsVersionMap = {
|
10286
|
-
'ME': '4.90',
|
10287
|
-
'NT 3.11': 'NT3.51',
|
10288
|
-
'NT 4.0': 'NT4.0',
|
10289
|
-
'2000': 'NT 5.0',
|
10290
|
-
'XP': ['NT 5.1', 'NT 5.2'],
|
10291
|
-
'Vista': 'NT 6.0',
|
10292
|
-
'7': 'NT 6.1',
|
10293
|
-
'8': 'NT 6.2',
|
10294
|
-
'8.1': 'NT 6.3',
|
10295
|
-
'10': ['NT 6.4', 'NT 10.0'],
|
10296
|
-
'RT': 'ARM'
|
10297
|
-
};
|
10298
|
-
|
10299
|
-
//////////////
|
10300
|
-
// Regex map
|
10301
|
-
/////////////
|
10302
|
-
|
10303
|
-
var regexes = {
|
10304
|
-
browser: [[/\b(?:crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS
|
10305
|
-
], [VERSION, [NAME, 'Chrome']], [/edg(?:e|ios|a)?\/([\w\.]+)/i // Microsoft Edge
|
10306
|
-
], [VERSION, [NAME, 'Edge']], [
|
10307
|
-
// Presto based
|
10308
|
-
/(opera mini)\/([-\w\.]+)/i,
|
10309
|
-
// Opera Mini
|
10310
|
-
/(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i,
|
10311
|
-
// Opera Mobi/Tablet
|
10312
|
-
/(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i // Opera
|
10313
|
-
], [NAME, VERSION], [/opios[\/ ]+([\w\.]+)/i // Opera mini on iphone >= 8.0
|
10314
|
-
], [VERSION, [NAME, OPERA + ' Mini']], [/\bopr\/([\w\.]+)/i // Opera Webkit
|
10315
|
-
], [VERSION, [NAME, OPERA]], [
|
10316
|
-
// Mixed
|
10317
|
-
/(kindle)\/([\w\.]+)/i,
|
10318
|
-
// Kindle
|
10319
|
-
/(lunascape|maxthon|netfront|jasmine|blazer)[\/ ]?([\w\.]*)/i,
|
10320
|
-
// Lunascape/Maxthon/Netfront/Jasmine/Blazer
|
10321
|
-
// Trident based
|
10322
|
-
/(avant |iemobile|slim)(?:browser)?[\/ ]?([\w\.]*)/i,
|
10323
|
-
// Avant/IEMobile/SlimBrowser
|
10324
|
-
/(ba?idubrowser)[\/ ]?([\w\.]+)/i,
|
10325
|
-
// Baidu Browser
|
10326
|
-
/(?:ms|\()(ie) ([\w\.]+)/i,
|
10327
|
-
// Internet Explorer
|
10328
|
-
|
10329
|
-
// Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
|
10330
|
-
/(flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|qq|duckduckgo)\/([-\w\.]+)/i,
|
10331
|
-
// Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ, aka ShouQ
|
10332
|
-
/(heytap|ovi)browser\/([\d\.]+)/i,
|
10333
|
-
// Heytap/Ovi
|
10334
|
-
/(weibo)__([\d\.]+)/i // Weibo
|
10335
|
-
], [NAME, VERSION], [/(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i // UCBrowser
|
10336
|
-
], [VERSION, [NAME, 'UC' + BROWSER]], [/microm.+\bqbcore\/([\w\.]+)/i,
|
10337
|
-
// WeChat Desktop for Windows Built-in Browser
|
10338
|
-
/\bqbcore\/([\w\.]+).+microm/i], [VERSION, [NAME, 'WeChat(Win) Desktop']], [/micromessenger\/([\w\.]+)/i // WeChat
|
10339
|
-
], [VERSION, [NAME, 'WeChat']], [/konqueror\/([\w\.]+)/i // Konqueror
|
10340
|
-
], [VERSION, [NAME, 'Konqueror']], [/trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i // IE11
|
10341
|
-
], [VERSION, [NAME, 'IE']], [/ya(?:search)?browser\/([\w\.]+)/i // Yandex
|
10342
|
-
], [VERSION, [NAME, 'Yandex']], [/(avast|avg)\/([\w\.]+)/i // Avast/AVG Secure Browser
|
10343
|
-
], [[NAME, /(.+)/, '$1 Secure ' + BROWSER], VERSION], [/\bfocus\/([\w\.]+)/i // Firefox Focus
|
10344
|
-
], [VERSION, [NAME, FIREFOX + ' Focus']], [/\bopt\/([\w\.]+)/i // Opera Touch
|
10345
|
-
], [VERSION, [NAME, OPERA + ' Touch']], [/coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser
|
10346
|
-
], [VERSION, [NAME, 'Coc Coc']], [/dolfin\/([\w\.]+)/i // Dolphin
|
10347
|
-
], [VERSION, [NAME, 'Dolphin']], [/coast\/([\w\.]+)/i // Opera Coast
|
10348
|
-
], [VERSION, [NAME, OPERA + ' Coast']], [/miuibrowser\/([\w\.]+)/i // MIUI Browser
|
10349
|
-
], [VERSION, [NAME, 'MIUI ' + BROWSER]], [/fxios\/([-\w\.]+)/i // Firefox for iOS
|
10350
|
-
], [VERSION, [NAME, FIREFOX]], [/\bqihu|(qi?ho?o?|360)browser/i // 360
|
10351
|
-
], [[NAME, '360 ' + BROWSER]], [/(oculus|samsung|sailfish|huawei)browser\/([\w\.]+)/i], [[NAME, /(.+)/, '$1 ' + BROWSER], VERSION], [
|
10352
|
-
// Oculus/Samsung/Sailfish/Huawei Browser
|
10353
|
-
/(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon
|
10354
|
-
], [[NAME, /_/g, ' '], VERSION], [/(electron)\/([\w\.]+) safari/i,
|
10355
|
-
// Electron-based App
|
10356
|
-
/(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i,
|
10357
|
-
// Tesla
|
10358
|
-
/m?(qqbrowser|baiduboxapp|2345Explorer)[\/ ]?([\w\.]+)/i // QQBrowser/Baidu App/2345 Browser
|
10359
|
-
], [NAME, VERSION], [/(metasr)[\/ ]?([\w\.]+)/i,
|
10360
|
-
// SouGouBrowser
|
10361
|
-
/(lbbrowser)/i,
|
10362
|
-
// LieBao Browser
|
10363
|
-
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android
|
10364
|
-
], [NAME], [
|
10365
|
-
// WebView
|
10366
|
-
/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i // Facebook App for iOS & Android
|
10367
|
-
], [[NAME, FACEBOOK], VERSION], [/(kakao(?:talk|story))[\/ ]([\w\.]+)/i,
|
10368
|
-
// Kakao App
|
10369
|
-
/(naver)\(.*?(\d+\.[\w\.]+).*\)/i,
|
10370
|
-
// Naver InApp
|
10371
|
-
/safari (line)\/([\w\.]+)/i,
|
10372
|
-
// Line App for iOS
|
10373
|
-
/\b(line)\/([\w\.]+)\/iab/i,
|
10374
|
-
// Line App for Android
|
10375
|
-
/(chromium|instagram)[\/ ]([-\w\.]+)/i // Chromium/Instagram
|
10376
|
-
], [NAME, VERSION], [/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
|
10377
|
-
], [VERSION, [NAME, 'GSA']], [/musical_ly(?:.+app_?version\/|_)([\w\.]+)/i // TikTok
|
10378
|
-
], [VERSION, [NAME, 'TikTok']], [/headlesschrome(?:\/([\w\.]+)| )/i // Chrome Headless
|
10379
|
-
], [VERSION, [NAME, CHROME + ' Headless']], [/ wv\).+(chrome)\/([\w\.]+)/i // Chrome WebView
|
10380
|
-
], [[NAME, CHROME + ' WebView'], VERSION], [/droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i // Android Browser
|
10381
|
-
], [VERSION, [NAME, 'Android ' + BROWSER]], [/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia
|
10382
|
-
], [NAME, VERSION], [/version\/([\w\.\,]+) .*mobile\/\w+ (safari)/i // Mobile Safari
|
10383
|
-
], [VERSION, [NAME, 'Mobile Safari']], [/version\/([\w(\.|\,)]+) .*(mobile ?safari|safari)/i // Safari & Safari Mobile
|
10384
|
-
], [VERSION, NAME], [/webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
|
10385
|
-
], [NAME, [VERSION, strMapper, oldSafariMap]], [/(webkit|khtml)\/([\w\.]+)/i], [NAME, VERSION], [
|
10386
|
-
// Gecko based
|
10387
|
-
/(navigator|netscape\d?)\/([-\w\.]+)/i // Netscape
|
10388
|
-
], [[NAME, 'Netscape'], VERSION], [/mobile vr; rv:([\w\.]+)\).+firefox/i // Firefox Reality
|
10389
|
-
], [VERSION, [NAME, FIREFOX + ' Reality']], [/ekiohf.+(flow)\/([\w\.]+)/i,
|
10390
|
-
// Flow
|
10391
|
-
/(swiftfox)/i,
|
10392
|
-
// Swiftfox
|
10393
|
-
/(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[\/ ]?([\w\.\+]+)/i,
|
10394
|
-
// IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror/Klar
|
10395
|
-
/(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
|
10396
|
-
// Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
|
10397
|
-
/(firefox)\/([\w\.]+)/i,
|
10398
|
-
// Other Firefox-based
|
10399
|
-
/(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i,
|
10400
|
-
// Mozilla
|
10401
|
-
|
10402
|
-
// Other
|
10403
|
-
/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
|
10404
|
-
// Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir/Obigo/Mosaic/Go/ICE/UP.Browser
|
10405
|
-
/(links) \(([\w\.]+)/i,
|
10406
|
-
// Links
|
10407
|
-
/panasonic;(viera)/i // Panasonic Viera
|
10408
|
-
], [NAME, VERSION], [/(cobalt)\/([\w\.]+)/i // Cobalt
|
10409
|
-
], [NAME, [VERSION, /master.|lts./, ""]]],
|
10410
|
-
cpu: [[/(?:(amd|x(?:(?:86|64)[-_])?|wow|win)64)[;\)]/i // AMD64 (x64)
|
10411
|
-
], [[ARCHITECTURE, 'amd64']], [/(ia32(?=;))/i // IA32 (quicktime)
|
10412
|
-
], [[ARCHITECTURE, lowerize]], [/((?:i[346]|x)86)[;\)]/i // IA32 (x86)
|
10413
|
-
], [[ARCHITECTURE, 'ia32']], [/\b(aarch64|arm(v?8e?l?|_?64))\b/i // ARM64
|
10414
|
-
], [[ARCHITECTURE, 'arm64']], [/\b(arm(?:v[67])?ht?n?[fl]p?)\b/i // ARMHF
|
10415
|
-
], [[ARCHITECTURE, 'armhf']], [
|
10416
|
-
// PocketPC mistakenly identified as PowerPC
|
10417
|
-
/windows (ce|mobile); ppc;/i], [[ARCHITECTURE, 'arm']], [/((?:ppc|powerpc)(?:64)?)(?: mac|;|\))/i // PowerPC
|
10418
|
-
], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [/(sun4\w)[;\)]/i // SPARC
|
10419
|
-
], [[ARCHITECTURE, 'sparc']], [/((?:avr32|ia64(?=;))|68k(?=\))|\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i
|
10420
|
-
// IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
|
10421
|
-
], [[ARCHITECTURE, lowerize]]],
|
10422
|
-
device: [[
|
10423
|
-
//////////////////////////
|
10424
|
-
// MOBILES & TABLETS
|
10425
|
-
/////////////////////////
|
10426
|
-
|
10427
|
-
// Samsung
|
10428
|
-
/\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [/\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?[\d]+a?|galaxy nexus)/i, /samsung[- ]([-\w]+)/i, /sec-(sgh\w+)/i], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [
|
10429
|
-
// Apple
|
10430
|
-
/(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i // iPod/iPhone
|
10431
|
-
], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [/\((ipad);[-\w\),; ]+apple/i,
|
10432
|
-
// iPad
|
10433
|
-
/applecoremedia\/[\w\.]+ \((ipad)/i, /\b(ipad)\d\d?,\d\d?[;\]].+ios/i], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [/(macintosh);/i], [MODEL, [VENDOR, APPLE]], [
|
10434
|
-
// Sharp
|
10435
|
-
/\b(sh-?[altvz]?\d\d[a-ekm]?)/i], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [
|
10436
|
-
// Huawei
|
10437
|
-
/\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [/(?:huawei|honor)([-\w ]+)[;\)]/i, /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [
|
10438
|
-
// Xiaomi
|
10439
|
-
/\b(poco[\w ]+)(?: bui|\))/i,
|
10440
|
-
// Xiaomi POCO
|
10441
|
-
/\b; (\w+) build\/hm\1/i,
|
10442
|
-
// Xiaomi Hongmi 'numeric' models
|
10443
|
-
/\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i,
|
10444
|
-
// Xiaomi Hongmi
|
10445
|
-
/\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i,
|
10446
|
-
// Xiaomi Redmi
|
10447
|
-
/\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i // Xiaomi Mi
|
10448
|
-
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [/\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i // Mi Pad tablets
|
10449
|
-
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [
|
10450
|
-
// OPPO
|
10451
|
-
/; (\w+) bui.+ oppo/i, /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [
|
10452
|
-
// Vivo
|
10453
|
-
/vivo (\w+)(?: bui|\))/i, /\b(v[12]\d{3}\w?[at])(?: bui|;)/i], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [
|
10454
|
-
// Realme
|
10455
|
-
/\b(rmx[12]\d{3})(?: bui|;|\))/i], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [
|
10456
|
-
// Motorola
|
10457
|
-
/\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i, /\bmot(?:orola)?[- ](\w*)/i, /((?:moto[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [/\b(mz60\d|xoom[2 ]{0,2}) build\//i], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [
|
10458
|
-
// LG
|
10459
|
-
/((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [/(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i, /\blg[-e;\/ ]+((?!browser|netcast|android tv)\w+)/i, /\blg-?([\d\w]+) bui/i], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [
|
10460
|
-
// Lenovo
|
10461
|
-
/(ideatab[-\w ]+)/i, /lenovo ?(s[56]000[-\w]+|tab(?:[\w ]+)|yt[-\d\w]{6}|tb[-\d\w]{6})/i], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [
|
10462
|
-
// Nokia
|
10463
|
-
/(?:maemo|nokia).*(n900|lumia \d+)/i, /nokia[-_ ]?([-\w\.]*)/i], [[MODEL, /_/g, ' '], [VENDOR, 'Nokia'], [TYPE, MOBILE]], [
|
10464
|
-
// Google
|
10465
|
-
/(pixel c)\b/i // Google Pixel C
|
10466
|
-
], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [/droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i // Google Pixel
|
10467
|
-
], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [
|
10468
|
-
// Sony
|
10469
|
-
/droid.+ (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [/sony tablet [ps]/i, /\b(?:sony)?sgp\w+(?: bui|\))/i], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [
|
10470
|
-
// OnePlus
|
10471
|
-
/ (kb2005|in20[12]5|be20[12][59])\b/i, /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [
|
10472
|
-
// Amazon
|
10473
|
-
/(alexa)webm/i, /(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i,
|
10474
|
-
// Kindle Fire without Silk / Echo Show
|
10475
|
-
/(kf[a-z]+)( bui|\)).+silk\//i // Kindle Fire HD
|
10476
|
-
], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [/((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i // Fire Phone
|
10477
|
-
], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [
|
10478
|
-
// BlackBerry
|
10479
|
-
/(playbook);[-\w\),; ]+(rim)/i // BlackBerry PlayBook
|
10480
|
-
], [MODEL, VENDOR, [TYPE, TABLET]], [/\b((?:bb[a-f]|st[hv])100-\d)/i, /\(bb10; (\w+)/i // BlackBerry 10
|
10481
|
-
], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [
|
10482
|
-
// Asus
|
10483
|
-
/(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [/ (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [
|
10484
|
-
// HTC
|
10485
|
-
/(nexus 9)/i // HTC Nexus 9
|
10486
|
-
], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [/(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i,
|
10487
|
-
// HTC
|
10488
|
-
|
10489
|
-
// ZTE
|
10490
|
-
/(zte)[- ]([\w ]+?)(?: bui|\/|\))/i, /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
|
10491
|
-
], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [
|
10492
|
-
// Acer
|
10493
|
-
/droid.+; ([ab][1-7]-?[0178a]\d\d?)/i], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [
|
10494
|
-
// Meizu
|
10495
|
-
/droid.+; (m[1-5] note) bui/i, /\bmz-([-\w]{2,})/i], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [
|
10496
|
-
// MIXED
|
10497
|
-
/(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[-_ ]?([-\w]*)/i,
|
10498
|
-
// BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron
|
10499
|
-
/(hp) ([\w ]+\w)/i,
|
10500
|
-
// HP iPAQ
|
10501
|
-
/(asus)-?(\w+)/i,
|
10502
|
-
// Asus
|
10503
|
-
/(microsoft); (lumia[\w ]+)/i,
|
10504
|
-
// Microsoft Lumia
|
10505
|
-
/(lenovo)[-_ ]?([-\w]+)/i,
|
10506
|
-
// Lenovo
|
10507
|
-
/(jolla)/i,
|
10508
|
-
// Jolla
|
10509
|
-
/(oppo) ?([\w ]+) bui/i // OPPO
|
10510
|
-
], [VENDOR, MODEL, [TYPE, MOBILE]], [/(kobo)\s(ereader|touch)/i,
|
10511
|
-
// Kobo
|
10512
|
-
/(archos) (gamepad2?)/i,
|
10513
|
-
// Archos
|
10514
|
-
/(hp).+(touchpad(?!.+tablet)|tablet)/i,
|
10515
|
-
// HP TouchPad
|
10516
|
-
/(kindle)\/([\w\.]+)/i,
|
10517
|
-
// Kindle
|
10518
|
-
/(nook)[\w ]+build\/(\w+)/i,
|
10519
|
-
// Nook
|
10520
|
-
/(dell) (strea[kpr\d ]*[\dko])/i,
|
10521
|
-
// Dell Streak
|
10522
|
-
/(le[- ]+pan)[- ]+(\w{1,9}) bui/i,
|
10523
|
-
// Le Pan Tablets
|
10524
|
-
/(trinity)[- ]*(t\d{3}) bui/i,
|
10525
|
-
// Trinity Tablets
|
10526
|
-
/(gigaset)[- ]+(q\w{1,9}) bui/i,
|
10527
|
-
// Gigaset Tablets
|
10528
|
-
/(vodafone) ([\w ]+)(?:\)| bui)/i // Vodafone
|
10529
|
-
], [VENDOR, MODEL, [TYPE, TABLET]], [/(surface duo)/i // Surface Duo
|
10530
|
-
], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [/droid [\d\.]+; (fp\du?)(?: b|\))/i // Fairphone
|
10531
|
-
], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [/(u304aa)/i // AT&T
|
10532
|
-
], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [/\bsie-(\w*)/i // Siemens
|
10533
|
-
], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [/\b(rct\w+) b/i // RCA Tablets
|
10534
|
-
], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [/\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets
|
10535
|
-
], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [/\b(q(?:mv|ta)\w+) b/i // Verizon Tablet
|
10536
|
-
], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [/\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet
|
10537
|
-
], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [/\b(tm\d{3}\w+) b/i], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [/\b(k88) b/i // ZTE K Series Tablet
|
10538
|
-
], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [/\b(nx\d{3}j) b/i // ZTE Nubia
|
10539
|
-
], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [/\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile
|
10540
|
-
], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [/\b(zur\d{3}) b/i // Swiss ZUR Tablet
|
10541
|
-
], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [/\b((zeki)?tb.*\b) b/i // Zeki Tablets
|
10542
|
-
], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [/\b([yr]\d{2}) b/i, /\b(dragon[- ]+touch |dt)(\w{5}) b/i // Dragon Touch Tablet
|
10543
|
-
], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [/\b(ns-?\w{0,9}) b/i // Insignia Tablets
|
10544
|
-
], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [/\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets
|
10545
|
-
], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [/\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones
|
10546
|
-
], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [/\b(lvtel\-)?(v1[12]) b/i // LvTel Phones
|
10547
|
-
], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [/\b(ph-1) /i // Essential PH-1
|
10548
|
-
], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [/\b(v(100md|700na|7011|917g).*\b) b/i // Envizen Tablets
|
10549
|
-
], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [/\b(trio[-\w\. ]+) b/i // MachSpeed Tablets
|
10550
|
-
], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [/\btu_(1491) b/i // Rotor Tablets
|
10551
|
-
], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [/(shield[\w ]+) b/i // Nvidia Shield Tablets
|
10552
|
-
], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [/(sprint) (\w+)/i // Sprint Phones
|
10553
|
-
], [VENDOR, MODEL, [TYPE, MOBILE]], [/(kin\.[onetw]{3})/i // Microsoft Kin
|
10554
|
-
], [[MODEL, /\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [/droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i // Zebra
|
10555
|
-
], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [/droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [
|
10556
|
-
///////////////////
|
10557
|
-
// SMARTTVS
|
10558
|
-
///////////////////
|
10559
|
-
|
10560
|
-
/smart-tv.+(samsung)/i // Samsung
|
10561
|
-
], [VENDOR, [TYPE, SMARTTV]], [/hbbtv.+maple;(\d+)/i], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [/(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i // LG SmartTV
|
10562
|
-
], [[VENDOR, LG], [TYPE, SMARTTV]], [/(apple) ?tv/i // Apple TV
|
10563
|
-
], [VENDOR, [MODEL, APPLE + ' TV'], [TYPE, SMARTTV]], [/crkey/i // Google Chromecast
|
10564
|
-
], [[MODEL, CHROME + 'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [/droid.+aft(\w)( bui|\))/i // Fire TV
|
10565
|
-
], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [/\(dtv[\);].+(aquos)/i, /(aquos-tv[\w ]+)\)/i // Sharp
|
10566
|
-
], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]], [/(bravia[\w ]+)( bui|\))/i // Sony
|
10567
|
-
], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [/(mitv-\w{5}) bui/i // Xiaomi
|
10568
|
-
], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [/Hbbtv.*(technisat) (.*);/i // TechniSAT
|
10569
|
-
], [VENDOR, MODEL, [TYPE, SMARTTV]], [/\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i,
|
10570
|
-
// Roku
|
10571
|
-
/hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i // HbbTV devices
|
10572
|
-
], [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]], [/\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i // SmartTV from Unidentified Vendors
|
10573
|
-
], [[TYPE, SMARTTV]], [
|
10574
|
-
///////////////////
|
10575
|
-
// CONSOLES
|
10576
|
-
///////////////////
|
10577
|
-
|
10578
|
-
/(ouya)/i,
|
10579
|
-
// Ouya
|
10580
|
-
/(nintendo) ([wids3utch]+)/i // Nintendo
|
10581
|
-
], [VENDOR, MODEL, [TYPE, CONSOLE]], [/droid.+; (shield) bui/i // Nvidia
|
10582
|
-
], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [/(playstation [345portablevi]+)/i // Playstation
|
10583
|
-
], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [/\b(xbox(?: one)?(?!; xbox))[\); ]/i // Microsoft Xbox
|
10584
|
-
], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [
|
10585
|
-
///////////////////
|
10586
|
-
// WEARABLES
|
10587
|
-
///////////////////
|
10588
|
-
|
10589
|
-
/((pebble))app/i // Pebble
|
10590
|
-
], [VENDOR, MODEL, [TYPE, WEARABLE]], [/(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i // Apple Watch
|
10591
|
-
], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [/droid.+; (glass) \d/i // Google Glass
|
10592
|
-
], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [/droid.+; (wt63?0{2,3})\)/i], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [/(quest( 2| pro)?)/i // Oculus Quest
|
10593
|
-
], [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]], [
|
10594
|
-
///////////////////
|
10595
|
-
// EMBEDDED
|
10596
|
-
///////////////////
|
10597
|
-
|
10598
|
-
/(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i // Tesla
|
10599
|
-
], [VENDOR, [TYPE, EMBEDDED]], [/(aeobc)\b/i // Echo Dot
|
10600
|
-
], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [
|
10601
|
-
////////////////////
|
10602
|
-
// MIXED (GENERIC)
|
10603
|
-
///////////////////
|
10604
|
-
|
10605
|
-
/droid .+?; ([^;]+?)(?: bui|\) applew).+? mobile safari/i // Android Phones from Unidentified Vendors
|
10606
|
-
], [MODEL, [TYPE, MOBILE]], [/droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors
|
10607
|
-
], [MODEL, [TYPE, TABLET]], [/\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i // Unidentifiable Tablet
|
10608
|
-
], [[TYPE, TABLET]], [/(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i // Unidentifiable Mobile
|
10609
|
-
], [[TYPE, MOBILE]], [/(android[-\w\. ]{0,9});.+buil/i // Generic Android Device
|
10610
|
-
], [MODEL, [VENDOR, 'Generic']]],
|
10611
|
-
engine: [[/windows.+ edge\/([\w\.]+)/i // EdgeHTML
|
10612
|
-
], [VERSION, [NAME, EDGE + 'HTML']], [/webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i // Blink
|
10613
|
-
], [VERSION, [NAME, 'Blink']], [/(presto)\/([\w\.]+)/i,
|
10614
|
-
// Presto
|
10615
|
-
/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i,
|
10616
|
-
// WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna
|
10617
|
-
/ekioh(flow)\/([\w\.]+)/i,
|
10618
|
-
// Flow
|
10619
|
-
/(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i,
|
10620
|
-
// KHTML/Tasman/Links
|
10621
|
-
/(icab)[\/ ]([23]\.[\d\.]+)/i,
|
10622
|
-
// iCab
|
10623
|
-
/\b(libweb)/i], [NAME, VERSION], [/rv\:([\w\.]{1,9})\b.+(gecko)/i // Gecko
|
10624
|
-
], [VERSION, NAME]],
|
10625
|
-
os: [[
|
10626
|
-
// Windows
|
10627
|
-
/microsoft (windows) (vista|xp)/i // Windows (iTunes)
|
10628
|
-
], [NAME, VERSION], [/(windows) nt 6\.2; (arm)/i,
|
10629
|
-
// Windows RT
|
10630
|
-
/(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i,
|
10631
|
-
// Windows Phone
|
10632
|
-
/(windows)[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i], [NAME, [VERSION, strMapper, windowsVersionMap]], [/(win(?=3|9|n)|win 9x )([nt\d\.]+)/i], [[NAME, 'Windows'], [VERSION, strMapper, windowsVersionMap]], [
|
10633
|
-
// iOS/macOS
|
10634
|
-
/ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i,
|
10635
|
-
// iOS
|
10636
|
-
/ios;fbsv\/([\d\.]+)/i, /cfnetwork\/.+darwin/i], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [/(mac os x) ?([\w\. ]*)/i, /(macintosh|mac_powerpc\b)(?!.+haiku)/i // Mac OS
|
10637
|
-
], [[NAME, MAC_OS], [VERSION, /_/g, '.']], [
|
10638
|
-
// Mobile OSes
|
10639
|
-
/droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i // Android-x86/HarmonyOS
|
10640
|
-
], [VERSION, NAME], [
|
10641
|
-
// Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS
|
10642
|
-
/(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\/ ]?([\w\.]*)/i, /(blackberry)\w*\/([\w\.]*)/i,
|
10643
|
-
// Blackberry
|
10644
|
-
/(tizen|kaios)[\/ ]([\w\.]+)/i,
|
10645
|
-
// Tizen/KaiOS
|
10646
|
-
/\((series40);/i // Series 40
|
10647
|
-
], [NAME, VERSION], [/\(bb(10);/i // BlackBerry 10
|
10648
|
-
], [VERSION, [NAME, BLACKBERRY]], [/(?:symbian ?os|symbos|s60(?=;)|series60)[-\/ ]?([\w\.]*)/i // Symbian
|
10649
|
-
], [VERSION, [NAME, 'Symbian']], [/mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS
|
10650
|
-
], [VERSION, [NAME, FIREFOX + ' OS']], [/web0s;.+rt(tv)/i, /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i // WebOS
|
10651
|
-
], [VERSION, [NAME, 'webOS']], [/watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i // watchOS
|
10652
|
-
], [VERSION, [NAME, 'watchOS']], [
|
10653
|
-
// Google Chromecast
|
10654
|
-
/crkey\/([\d\.]+)/i // Google Chromecast
|
10655
|
-
], [VERSION, [NAME, CHROME + 'cast']], [/(cros) [\w]+(?:\)| ([\w\.]+)\b)/i // Chromium OS
|
10656
|
-
], [[NAME, CHROMIUM_OS], VERSION], [
|
10657
|
-
// Smart TVs
|
10658
|
-
/panasonic;(viera)/i,
|
10659
|
-
// Panasonic Viera
|
10660
|
-
/(netrange)mmh/i,
|
10661
|
-
// Netrange
|
10662
|
-
/(nettv)\/(\d+\.[\w\.]+)/i,
|
10663
|
-
// NetTV
|
10664
|
-
|
10665
|
-
// Console
|
10666
|
-
/(nintendo|playstation) ([wids345portablevuch]+)/i,
|
10667
|
-
// Nintendo/Playstation
|
10668
|
-
/(xbox); +xbox ([^\);]+)/i,
|
10669
|
-
// Microsoft Xbox (360, One, X, S, Series X, Series S)
|
10670
|
-
|
10671
|
-
// Other
|
10672
|
-
/\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i,
|
10673
|
-
// Joli/Palm
|
10674
|
-
/(mint)[\/\(\) ]?(\w*)/i,
|
10675
|
-
// Mint
|
10676
|
-
/(mageia|vectorlinux)[; ]/i,
|
10677
|
-
// Mageia/VectorLinux
|
10678
|
-
/([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,
|
10679
|
-
// Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire
|
10680
|
-
/(hurd|linux) ?([\w\.]*)/i,
|
10681
|
-
// Hurd/Linux
|
10682
|
-
/(gnu) ?([\w\.]*)/i,
|
10683
|
-
// GNU
|
10684
|
-
/\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i,
|
10685
|
-
// FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly
|
10686
|
-
/(haiku) (\w+)/i // Haiku
|
10687
|
-
], [NAME, VERSION], [/(sunos) ?([\w\.\d]*)/i // Solaris
|
10688
|
-
], [[NAME, 'Solaris'], VERSION], [/((?:open)?solaris)[-\/ ]?([\w\.]*)/i,
|
10689
|
-
// Solaris
|
10690
|
-
/(aix) ((\d)(?=\.|\)| )[\w\.])*/i,
|
10691
|
-
// AIX
|
10692
|
-
/\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i,
|
10693
|
-
// BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS
|
10694
|
-
/(unix) ?([\w\.]*)/i // UNIX
|
10695
|
-
], [NAME, VERSION]]
|
10696
|
-
};
|
10697
|
-
|
10698
|
-
/////////////////
|
10699
|
-
// Constructor
|
10700
|
-
////////////////
|
10701
|
-
|
10702
|
-
var UAParser = function (ua, extensions) {
|
10703
|
-
if (typeof ua === OBJ_TYPE) {
|
10704
|
-
extensions = ua;
|
10705
|
-
ua = undefined$1;
|
10706
|
-
}
|
10707
|
-
if (!(this instanceof UAParser)) {
|
10708
|
-
return new UAParser(ua, extensions).getResult();
|
10709
|
-
}
|
10710
|
-
var _navigator = typeof window !== UNDEF_TYPE && window.navigator ? window.navigator : undefined$1;
|
10711
|
-
var _ua = ua || (_navigator && _navigator.userAgent ? _navigator.userAgent : EMPTY);
|
10712
|
-
var _uach = _navigator && _navigator.userAgentData ? _navigator.userAgentData : undefined$1;
|
10713
|
-
var _rgxmap = extensions ? extend(regexes, extensions) : regexes;
|
10714
|
-
var _isSelfNav = _navigator && _navigator.userAgent == _ua;
|
10715
|
-
this.getBrowser = function () {
|
10716
|
-
var _browser = {};
|
10717
|
-
_browser[NAME] = undefined$1;
|
10718
|
-
_browser[VERSION] = undefined$1;
|
10719
|
-
rgxMapper.call(_browser, _ua, _rgxmap.browser);
|
10720
|
-
_browser[MAJOR] = majorize(_browser[VERSION]);
|
10721
|
-
// Brave-specific detection
|
10722
|
-
if (_isSelfNav && _navigator && _navigator.brave && typeof _navigator.brave.isBrave == FUNC_TYPE) {
|
10723
|
-
_browser[NAME] = 'Brave';
|
10724
|
-
}
|
10725
|
-
return _browser;
|
10726
|
-
};
|
10727
|
-
this.getCPU = function () {
|
10728
|
-
var _cpu = {};
|
10729
|
-
_cpu[ARCHITECTURE] = undefined$1;
|
10730
|
-
rgxMapper.call(_cpu, _ua, _rgxmap.cpu);
|
10731
|
-
return _cpu;
|
10732
|
-
};
|
10733
|
-
this.getDevice = function () {
|
10734
|
-
var _device = {};
|
10735
|
-
_device[VENDOR] = undefined$1;
|
10736
|
-
_device[MODEL] = undefined$1;
|
10737
|
-
_device[TYPE] = undefined$1;
|
10738
|
-
rgxMapper.call(_device, _ua, _rgxmap.device);
|
10739
|
-
if (_isSelfNav && !_device[TYPE] && _uach && _uach.mobile) {
|
10740
|
-
_device[TYPE] = MOBILE;
|
10741
|
-
}
|
10742
|
-
// iPadOS-specific detection: identified as Mac, but has some iOS-only properties
|
10743
|
-
if (_isSelfNav && _device[MODEL] == 'Macintosh' && _navigator && typeof _navigator.standalone !== UNDEF_TYPE && _navigator.maxTouchPoints && _navigator.maxTouchPoints > 2) {
|
10744
|
-
_device[MODEL] = 'iPad';
|
10745
|
-
_device[TYPE] = TABLET;
|
10746
|
-
}
|
10747
|
-
return _device;
|
10748
|
-
};
|
10749
|
-
this.getEngine = function () {
|
10750
|
-
var _engine = {};
|
10751
|
-
_engine[NAME] = undefined$1;
|
10752
|
-
_engine[VERSION] = undefined$1;
|
10753
|
-
rgxMapper.call(_engine, _ua, _rgxmap.engine);
|
10754
|
-
return _engine;
|
10755
|
-
};
|
10756
|
-
this.getOS = function () {
|
10757
|
-
var _os = {};
|
10758
|
-
_os[NAME] = undefined$1;
|
10759
|
-
_os[VERSION] = undefined$1;
|
10760
|
-
rgxMapper.call(_os, _ua, _rgxmap.os);
|
10761
|
-
if (_isSelfNav && !_os[NAME] && _uach && _uach.platform != 'Unknown') {
|
10762
|
-
_os[NAME] = _uach.platform.replace(/chrome os/i, CHROMIUM_OS).replace(/macos/i, MAC_OS); // backward compatibility
|
10763
|
-
}
|
10764
|
-
|
10765
|
-
return _os;
|
10766
|
-
};
|
10767
|
-
this.getResult = function () {
|
10768
|
-
return {
|
10769
|
-
ua: this.getUA(),
|
10770
|
-
browser: this.getBrowser(),
|
10771
|
-
engine: this.getEngine(),
|
10772
|
-
os: this.getOS(),
|
10773
|
-
device: this.getDevice(),
|
10774
|
-
cpu: this.getCPU()
|
10775
|
-
};
|
10776
|
-
};
|
10777
|
-
this.getUA = function () {
|
10778
|
-
return _ua;
|
10779
|
-
};
|
10780
|
-
this.setUA = function (ua) {
|
10781
|
-
_ua = typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
|
10782
|
-
return this;
|
10783
|
-
};
|
10784
|
-
this.setUA(_ua);
|
10785
|
-
return this;
|
10786
|
-
};
|
10787
|
-
UAParser.VERSION = LIBVERSION;
|
10788
|
-
UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]);
|
10789
|
-
UAParser.CPU = enumerize([ARCHITECTURE]);
|
10790
|
-
UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);
|
10791
|
-
UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);
|
10792
|
-
|
10793
|
-
///////////
|
10794
|
-
// Export
|
10795
|
-
//////////
|
10796
|
-
|
10797
|
-
// check js environment
|
10798
|
-
{
|
10799
|
-
// nodejs env
|
10800
|
-
if (module.exports) {
|
10801
|
-
exports = module.exports = UAParser;
|
10802
|
-
}
|
10803
|
-
exports.UAParser = UAParser;
|
10804
|
-
}
|
10805
|
-
|
10806
|
-
// jQuery/Zepto specific (optional)
|
10807
|
-
// Note:
|
10808
|
-
// In AMD env the global scope should be kept clean, but jQuery is an exception.
|
10809
|
-
// jQuery always exports to global scope, unless jQuery.noConflict(true) is used,
|
10810
|
-
// and we should catch that.
|
10811
|
-
var $ = typeof window !== UNDEF_TYPE && (window.jQuery || window.Zepto);
|
10812
|
-
if ($ && !$.ua) {
|
10813
|
-
var parser = new UAParser();
|
10814
|
-
$.ua = parser.getResult();
|
10815
|
-
$.ua.get = function () {
|
10816
|
-
return parser.getUA();
|
10817
|
-
};
|
10818
|
-
$.ua.set = function (ua) {
|
10819
|
-
parser.setUA(ua);
|
10820
|
-
var result = parser.getResult();
|
10821
|
-
for (var prop in result) {
|
10822
|
-
$.ua[prop] = result[prop];
|
10823
|
-
}
|
10824
|
-
};
|
10825
|
-
}
|
10826
|
-
})(typeof window === 'object' ? window : commonjsGlobal);
|
10827
|
-
})(uaParser, uaParser.exports);
|
10828
|
-
var uaParserExports = uaParser.exports;
|
10829
|
-
var UAParser = /*@__PURE__*/getDefaultExportFromCjs(uaParserExports);
|
10830
|
-
|
10831
|
-
var version$1 = "1.9.4";
|
10832
|
-
|
10833
|
-
const version = version$1;
|
10834
|
-
const protocolVersion = 9;
|
10835
|
-
|
10836
|
-
function mergeDefaultOptions(options, audioDefaults, videoDefaults) {
|
10837
|
-
const opts = Object.assign({}, options);
|
10838
|
-
if (opts.audio === true) opts.audio = {};
|
10839
|
-
if (opts.video === true) opts.video = {};
|
10840
|
-
// use defaults
|
10841
|
-
if (opts.audio) {
|
10842
|
-
mergeObjectWithoutOverwriting(opts.audio, audioDefaults);
|
10843
|
-
}
|
10844
|
-
if (opts.video) {
|
10845
|
-
mergeObjectWithoutOverwriting(opts.video, videoDefaults);
|
10093
|
+
/* eslint-disable */
|
10094
|
+
var SignalTarget;
|
10095
|
+
(function (SignalTarget) {
|
10096
|
+
SignalTarget[SignalTarget["PUBLISHER"] = 0] = "PUBLISHER";
|
10097
|
+
SignalTarget[SignalTarget["SUBSCRIBER"] = 1] = "SUBSCRIBER";
|
10098
|
+
SignalTarget[SignalTarget["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
|
10099
|
+
})(SignalTarget || (SignalTarget = {}));
|
10100
|
+
function signalTargetFromJSON(object) {
|
10101
|
+
switch (object) {
|
10102
|
+
case 0:
|
10103
|
+
case "PUBLISHER":
|
10104
|
+
return SignalTarget.PUBLISHER;
|
10105
|
+
case 1:
|
10106
|
+
case "SUBSCRIBER":
|
10107
|
+
return SignalTarget.SUBSCRIBER;
|
10108
|
+
case -1:
|
10109
|
+
case "UNRECOGNIZED":
|
10110
|
+
default:
|
10111
|
+
return SignalTarget.UNRECOGNIZED;
|
10846
10112
|
}
|
10847
|
-
return opts;
|
10848
|
-
}
|
10849
|
-
function mergeObjectWithoutOverwriting(mainObject, objectToMerge) {
|
10850
|
-
Object.keys(objectToMerge).forEach(key => {
|
10851
|
-
if (mainObject[key] === undefined) mainObject[key] = objectToMerge[key];
|
10852
|
-
});
|
10853
|
-
return mainObject;
|
10854
10113
|
}
|
10855
|
-
function
|
10856
|
-
|
10857
|
-
|
10858
|
-
|
10859
|
-
|
10860
|
-
|
10861
|
-
|
10862
|
-
|
10863
|
-
|
10864
|
-
switch (key) {
|
10865
|
-
case 'resolution':
|
10866
|
-
// flatten VideoResolution fields
|
10867
|
-
mergeObjectWithoutOverwriting(target, source.resolution);
|
10868
|
-
break;
|
10869
|
-
default:
|
10870
|
-
target[key] = source[key];
|
10871
|
-
}
|
10872
|
-
});
|
10873
|
-
constraints.video = videoOptions;
|
10874
|
-
} else {
|
10875
|
-
constraints.video = options.video;
|
10876
|
-
}
|
10877
|
-
} else {
|
10878
|
-
constraints.video = false;
|
10879
|
-
}
|
10880
|
-
if (options.audio) {
|
10881
|
-
if (typeof options.audio === 'object') {
|
10882
|
-
constraints.audio = options.audio;
|
10883
|
-
} else {
|
10884
|
-
constraints.audio = true;
|
10885
|
-
}
|
10886
|
-
} else {
|
10887
|
-
constraints.audio = false;
|
10114
|
+
function signalTargetToJSON(object) {
|
10115
|
+
switch (object) {
|
10116
|
+
case SignalTarget.PUBLISHER:
|
10117
|
+
return "PUBLISHER";
|
10118
|
+
case SignalTarget.SUBSCRIBER:
|
10119
|
+
return "SUBSCRIBER";
|
10120
|
+
case SignalTarget.UNRECOGNIZED:
|
10121
|
+
default:
|
10122
|
+
return "UNRECOGNIZED";
|
10888
10123
|
}
|
10889
|
-
return constraints;
|
10890
10124
|
}
|
10891
|
-
|
10892
|
-
|
10893
|
-
|
10894
|
-
|
10895
|
-
|
10896
|
-
|
10897
|
-
|
10898
|
-
|
10899
|
-
|
10900
|
-
|
10901
|
-
|
10902
|
-
|
10903
|
-
|
10904
|
-
|
10905
|
-
|
10906
|
-
|
10907
|
-
|
10908
|
-
|
10909
|
-
|
10910
|
-
return !someNoise;
|
10911
|
-
}
|
10912
|
-
return false;
|
10913
|
-
});
|
10125
|
+
var StreamState;
|
10126
|
+
(function (StreamState) {
|
10127
|
+
StreamState[StreamState["ACTIVE"] = 0] = "ACTIVE";
|
10128
|
+
StreamState[StreamState["PAUSED"] = 1] = "PAUSED";
|
10129
|
+
StreamState[StreamState["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
|
10130
|
+
})(StreamState || (StreamState = {}));
|
10131
|
+
function streamStateFromJSON(object) {
|
10132
|
+
switch (object) {
|
10133
|
+
case 0:
|
10134
|
+
case "ACTIVE":
|
10135
|
+
return StreamState.ACTIVE;
|
10136
|
+
case 1:
|
10137
|
+
case "PAUSED":
|
10138
|
+
return StreamState.PAUSED;
|
10139
|
+
case -1:
|
10140
|
+
case "UNRECOGNIZED":
|
10141
|
+
default:
|
10142
|
+
return StreamState.UNRECOGNIZED;
|
10143
|
+
}
|
10914
10144
|
}
|
10915
|
-
|
10916
|
-
|
10917
|
-
|
10918
|
-
|
10919
|
-
|
10920
|
-
|
10921
|
-
|
10922
|
-
|
10923
|
-
|
10924
|
-
latencyHint: 'interactive'
|
10925
|
-
});
|
10145
|
+
function streamStateToJSON(object) {
|
10146
|
+
switch (object) {
|
10147
|
+
case StreamState.ACTIVE:
|
10148
|
+
return "ACTIVE";
|
10149
|
+
case StreamState.PAUSED:
|
10150
|
+
return "PAUSED";
|
10151
|
+
case StreamState.UNRECOGNIZED:
|
10152
|
+
default:
|
10153
|
+
return "UNRECOGNIZED";
|
10926
10154
|
}
|
10927
10155
|
}
|
10928
|
-
|
10929
|
-
|
10930
|
-
|
10931
|
-
|
10932
|
-
|
10933
|
-
|
10934
|
-
|
10156
|
+
var CandidateProtocol;
|
10157
|
+
(function (CandidateProtocol) {
|
10158
|
+
CandidateProtocol[CandidateProtocol["UDP"] = 0] = "UDP";
|
10159
|
+
CandidateProtocol[CandidateProtocol["TCP"] = 1] = "TCP";
|
10160
|
+
CandidateProtocol[CandidateProtocol["TLS"] = 2] = "TLS";
|
10161
|
+
CandidateProtocol[CandidateProtocol["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
|
10162
|
+
})(CandidateProtocol || (CandidateProtocol = {}));
|
10163
|
+
function candidateProtocolFromJSON(object) {
|
10164
|
+
switch (object) {
|
10165
|
+
case 0:
|
10166
|
+
case "UDP":
|
10167
|
+
return CandidateProtocol.UDP;
|
10168
|
+
case 1:
|
10169
|
+
case "TCP":
|
10170
|
+
return CandidateProtocol.TCP;
|
10171
|
+
case 2:
|
10172
|
+
case "TLS":
|
10173
|
+
return CandidateProtocol.TLS;
|
10174
|
+
case -1:
|
10175
|
+
case "UNRECOGNIZED":
|
10176
|
+
default:
|
10177
|
+
return CandidateProtocol.UNRECOGNIZED;
|
10935
10178
|
}
|
10936
|
-
return [packed, ''];
|
10937
10179
|
}
|
10938
|
-
function
|
10939
|
-
|
10940
|
-
|
10941
|
-
|
10180
|
+
function candidateProtocolToJSON(object) {
|
10181
|
+
switch (object) {
|
10182
|
+
case CandidateProtocol.UDP:
|
10183
|
+
return "UDP";
|
10184
|
+
case CandidateProtocol.TCP:
|
10185
|
+
return "TCP";
|
10186
|
+
case CandidateProtocol.TLS:
|
10187
|
+
return "TLS";
|
10188
|
+
case CandidateProtocol.UNRECOGNIZED:
|
10189
|
+
default:
|
10190
|
+
return "UNRECOGNIZED";
|
10191
|
+
}
|
10942
10192
|
}
|
10943
|
-
|
10944
|
-
|
10945
|
-
|
10946
|
-
}
|
10947
|
-
/** @internal */
|
10948
|
-
function supportsAddTrack() {
|
10949
|
-
return 'addTrack' in RTCPeerConnection.prototype;
|
10950
|
-
}
|
10951
|
-
function supportsAdaptiveStream() {
|
10952
|
-
return typeof ResizeObserver !== undefined && typeof IntersectionObserver !== undefined;
|
10953
|
-
}
|
10954
|
-
function supportsDynacast() {
|
10955
|
-
return supportsTransceiver();
|
10956
|
-
}
|
10957
|
-
function supportsAV1() {
|
10958
|
-
if (!('getCapabilities' in RTCRtpSender)) {
|
10959
|
-
return false;
|
10960
|
-
}
|
10961
|
-
const capabilities = RTCRtpSender.getCapabilities('video');
|
10962
|
-
let hasAV1 = false;
|
10963
|
-
if (capabilities) {
|
10964
|
-
for (const codec of capabilities.codecs) {
|
10965
|
-
if (codec.mimeType === 'video/AV1') {
|
10966
|
-
hasAV1 = true;
|
10967
|
-
break;
|
10968
|
-
}
|
10969
|
-
}
|
10970
|
-
}
|
10971
|
-
return hasAV1;
|
10972
|
-
}
|
10973
|
-
function supportsVP9() {
|
10974
|
-
if (!('getCapabilities' in RTCRtpSender)) {
|
10975
|
-
// technically speaking FireFox supports VP9, but SVC publishing is broken
|
10976
|
-
// https://bugzilla.mozilla.org/show_bug.cgi?id=1633876
|
10977
|
-
return false;
|
10978
|
-
}
|
10979
|
-
const capabilities = RTCRtpSender.getCapabilities('video');
|
10980
|
-
let hasVP9 = false;
|
10981
|
-
if (capabilities) {
|
10982
|
-
for (const codec of capabilities.codecs) {
|
10983
|
-
if (codec.mimeType === 'video/VP9') {
|
10984
|
-
hasVP9 = true;
|
10985
|
-
break;
|
10986
|
-
}
|
10987
|
-
}
|
10988
|
-
}
|
10989
|
-
return hasVP9;
|
10990
|
-
}
|
10991
|
-
function isSVCCodec(codec) {
|
10992
|
-
return codec === 'av1' || codec === 'vp9';
|
10993
|
-
}
|
10994
|
-
function supportsSetSinkId(elm) {
|
10995
|
-
if (!document) {
|
10996
|
-
return false;
|
10997
|
-
}
|
10998
|
-
if (!elm) {
|
10999
|
-
elm = document.createElement('audio');
|
11000
|
-
}
|
11001
|
-
return 'setSinkId' in elm;
|
11002
|
-
}
|
11003
|
-
const setCodecPreferencesVersions = {
|
11004
|
-
Chrome: '100',
|
11005
|
-
Chromium: '100',
|
11006
|
-
Safari: '15',
|
11007
|
-
Firefox: '100',
|
11008
|
-
Edge: '100',
|
11009
|
-
Brave: '1.40'
|
11010
|
-
};
|
11011
|
-
function supportsSetCodecPreferences(transceiver) {
|
11012
|
-
if (!isWeb()) {
|
11013
|
-
return false;
|
11014
|
-
}
|
11015
|
-
if (!('setCodecPreferences' in transceiver)) {
|
11016
|
-
return false;
|
11017
|
-
}
|
11018
|
-
const uap = UAParser();
|
11019
|
-
if (!uap.browser.name || !uap.browser.version) {
|
11020
|
-
// version is required
|
11021
|
-
return false;
|
11022
|
-
}
|
11023
|
-
const v = setCodecPreferencesVersions[uap.browser.name];
|
11024
|
-
if (v) {
|
11025
|
-
return compareVersions(uap.browser.version, v) >= 0;
|
11026
|
-
}
|
11027
|
-
return false;
|
11028
|
-
}
|
11029
|
-
function isBrowserSupported() {
|
11030
|
-
return supportsTransceiver() || supportsAddTrack();
|
11031
|
-
}
|
11032
|
-
function isFireFox() {
|
11033
|
-
if (!isWeb()) return false;
|
11034
|
-
return navigator.userAgent.indexOf('Firefox') !== -1;
|
11035
|
-
}
|
11036
|
-
function isChromiumBased() {
|
11037
|
-
if (!isWeb()) return false;
|
11038
|
-
return navigator.userAgent.indexOf('Chrom') !== -1;
|
11039
|
-
}
|
11040
|
-
function isSafari() {
|
11041
|
-
if (!isWeb()) return false;
|
11042
|
-
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
11043
|
-
}
|
11044
|
-
function isMobile() {
|
11045
|
-
if (!isWeb()) return false;
|
11046
|
-
return /Tablet|iPad|Mobile|Android|BlackBerry/.test(navigator.userAgent);
|
11047
|
-
}
|
11048
|
-
function isWeb() {
|
11049
|
-
return typeof document !== 'undefined';
|
11050
|
-
}
|
11051
|
-
function isReactNative() {
|
11052
|
-
// navigator.product is deprecated on browsers, but will be set appropriately for react-native.
|
11053
|
-
return navigator.product == 'ReactNative';
|
11054
|
-
}
|
11055
|
-
function isCloud(serverUrl) {
|
11056
|
-
return serverUrl.hostname.endsWith('.livekit.cloud');
|
11057
|
-
}
|
11058
|
-
function getLKReactNativeInfo() {
|
11059
|
-
// global defined only for ReactNative.
|
11060
|
-
// @ts-ignore
|
11061
|
-
if (global && global.LiveKitReactNativeGlobal) {
|
11062
|
-
// @ts-ignore
|
11063
|
-
return global.LiveKitReactNativeGlobal;
|
11064
|
-
}
|
11065
|
-
return undefined;
|
11066
|
-
}
|
11067
|
-
function getReactNativeOs() {
|
11068
|
-
if (!isReactNative()) {
|
11069
|
-
return undefined;
|
11070
|
-
}
|
11071
|
-
let info = getLKReactNativeInfo();
|
11072
|
-
if (info) {
|
11073
|
-
return info.platform;
|
11074
|
-
}
|
11075
|
-
return undefined;
|
11076
|
-
}
|
11077
|
-
function getDevicePixelRatio() {
|
11078
|
-
if (isWeb()) {
|
11079
|
-
return window.devicePixelRatio;
|
11080
|
-
}
|
11081
|
-
if (isReactNative()) {
|
11082
|
-
let info = getLKReactNativeInfo();
|
11083
|
-
if (info) {
|
11084
|
-
return info.devicePixelRatio;
|
11085
|
-
}
|
11086
|
-
}
|
11087
|
-
return 1;
|
11088
|
-
}
|
11089
|
-
function compareVersions(v1, v2) {
|
11090
|
-
const parts1 = v1.split('.');
|
11091
|
-
const parts2 = v2.split('.');
|
11092
|
-
const k = Math.min(v1.length, v2.length);
|
11093
|
-
for (let i = 0; i < k; ++i) {
|
11094
|
-
const p1 = parseInt(parts1[i], 10);
|
11095
|
-
const p2 = parseInt(parts2[i], 10);
|
11096
|
-
if (p1 > p2) return 1;
|
11097
|
-
if (p1 < p2) return -1;
|
11098
|
-
}
|
11099
|
-
return parts1.length == parts2.length ? 0 : parts1.length < parts2.length ? -1 : 1;
|
11100
|
-
}
|
11101
|
-
function roDispatchCallback(entries) {
|
11102
|
-
for (const entry of entries) {
|
11103
|
-
entry.target.handleResize(entry);
|
11104
|
-
}
|
11105
|
-
}
|
11106
|
-
function ioDispatchCallback(entries) {
|
11107
|
-
for (const entry of entries) {
|
11108
|
-
entry.target.handleVisibilityChanged(entry);
|
11109
|
-
}
|
11110
|
-
}
|
11111
|
-
let resizeObserver = null;
|
11112
|
-
const getResizeObserver = () => {
|
11113
|
-
if (!resizeObserver) resizeObserver = new ResizeObserver(roDispatchCallback);
|
11114
|
-
return resizeObserver;
|
11115
|
-
};
|
11116
|
-
let intersectionObserver = null;
|
11117
|
-
const getIntersectionObserver = () => {
|
11118
|
-
if (!intersectionObserver) intersectionObserver = new IntersectionObserver(ioDispatchCallback, {
|
11119
|
-
root: document,
|
11120
|
-
rootMargin: '0px'
|
11121
|
-
});
|
11122
|
-
return intersectionObserver;
|
11123
|
-
};
|
11124
|
-
function getClientInfo() {
|
11125
|
-
var _a;
|
11126
|
-
const info = ClientInfo.fromPartial({
|
11127
|
-
sdk: ClientInfo_SDK.JS,
|
11128
|
-
protocol: protocolVersion,
|
11129
|
-
version
|
11130
|
-
});
|
11131
|
-
if (isReactNative()) {
|
11132
|
-
info.os = (_a = getReactNativeOs()) !== null && _a !== void 0 ? _a : '';
|
11133
|
-
}
|
11134
|
-
return info;
|
11135
|
-
}
|
11136
|
-
let emptyVideoStreamTrack;
|
11137
|
-
function getEmptyVideoStreamTrack() {
|
11138
|
-
if (!emptyVideoStreamTrack) {
|
11139
|
-
emptyVideoStreamTrack = createDummyVideoStreamTrack();
|
11140
|
-
}
|
11141
|
-
return emptyVideoStreamTrack;
|
11142
|
-
}
|
11143
|
-
function createDummyVideoStreamTrack() {
|
11144
|
-
let width = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 16;
|
11145
|
-
let height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 16;
|
11146
|
-
let enabled = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
11147
|
-
let paintContent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
11148
|
-
const canvas = document.createElement('canvas');
|
11149
|
-
// the canvas size is set to 16 by default, because electron apps seem to fail with smaller values
|
11150
|
-
canvas.width = width;
|
11151
|
-
canvas.height = height;
|
11152
|
-
const ctx = canvas.getContext('2d');
|
11153
|
-
ctx === null || ctx === void 0 ? void 0 : ctx.fillRect(0, 0, canvas.width, canvas.height);
|
11154
|
-
if (paintContent && ctx) {
|
11155
|
-
ctx.beginPath();
|
11156
|
-
ctx.arc(width / 2, height / 2, 50, 0, Math.PI * 2, true);
|
11157
|
-
ctx.closePath();
|
11158
|
-
ctx.fillStyle = 'grey';
|
11159
|
-
ctx.fill();
|
11160
|
-
}
|
11161
|
-
// @ts-ignore
|
11162
|
-
const dummyStream = canvas.captureStream();
|
11163
|
-
const [dummyTrack] = dummyStream.getTracks();
|
11164
|
-
if (!dummyTrack) {
|
11165
|
-
throw Error('Could not get empty media stream video track');
|
11166
|
-
}
|
11167
|
-
dummyTrack.enabled = enabled;
|
11168
|
-
return dummyTrack;
|
11169
|
-
}
|
11170
|
-
let emptyAudioStreamTrack;
|
11171
|
-
function getEmptyAudioStreamTrack() {
|
11172
|
-
if (!emptyAudioStreamTrack) {
|
11173
|
-
// implementation adapted from https://blog.mozilla.org/webrtc/warm-up-with-replacetrack/
|
11174
|
-
const ctx = new AudioContext();
|
11175
|
-
const oscillator = ctx.createOscillator();
|
11176
|
-
const dst = ctx.createMediaStreamDestination();
|
11177
|
-
oscillator.connect(dst);
|
11178
|
-
oscillator.start();
|
11179
|
-
[emptyAudioStreamTrack] = dst.stream.getAudioTracks();
|
11180
|
-
if (!emptyAudioStreamTrack) {
|
11181
|
-
throw Error('Could not get empty media stream audio track');
|
11182
|
-
}
|
11183
|
-
emptyAudioStreamTrack.enabled = false;
|
11184
|
-
}
|
11185
|
-
return emptyAudioStreamTrack;
|
11186
|
-
}
|
11187
|
-
class Future {
|
11188
|
-
constructor(futureBase, onFinally) {
|
11189
|
-
this.onFinally = onFinally;
|
11190
|
-
this.promise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
11191
|
-
this.resolve = resolve;
|
11192
|
-
this.reject = reject;
|
11193
|
-
if (futureBase) {
|
11194
|
-
yield futureBase(resolve, reject);
|
11195
|
-
}
|
11196
|
-
})).finally(() => {
|
11197
|
-
var _a;
|
11198
|
-
return (_a = this.onFinally) === null || _a === void 0 ? void 0 : _a.call(this);
|
11199
|
-
});
|
11200
|
-
}
|
11201
|
-
}
|
11202
|
-
/**
|
11203
|
-
* Creates and returns an analyser web audio node that is attached to the provided track.
|
11204
|
-
* Additionally returns a convenience method `calculateVolume` to perform instant volume readings on that track.
|
11205
|
-
* Call the returned `cleanup` function to close the audioContext that has been created for the instance of this helper
|
11206
|
-
*/
|
11207
|
-
function createAudioAnalyser(track, options) {
|
11208
|
-
const opts = Object.assign({
|
11209
|
-
cloneTrack: false,
|
11210
|
-
fftSize: 2048,
|
11211
|
-
smoothingTimeConstant: 0.8,
|
11212
|
-
minDecibels: -100,
|
11213
|
-
maxDecibels: -80
|
11214
|
-
}, options);
|
11215
|
-
const audioContext = getNewAudioContext();
|
11216
|
-
if (!audioContext) {
|
11217
|
-
throw new Error('Audio Context not supported on this browser');
|
11218
|
-
}
|
11219
|
-
const streamTrack = opts.cloneTrack ? track.mediaStreamTrack.clone() : track.mediaStreamTrack;
|
11220
|
-
const mediaStreamSource = audioContext.createMediaStreamSource(new MediaStream([streamTrack]));
|
11221
|
-
const analyser = audioContext.createAnalyser();
|
11222
|
-
analyser.minDecibels = opts.minDecibels;
|
11223
|
-
analyser.maxDecibels = opts.maxDecibels;
|
11224
|
-
analyser.fftSize = opts.fftSize;
|
11225
|
-
analyser.smoothingTimeConstant = opts.smoothingTimeConstant;
|
11226
|
-
mediaStreamSource.connect(analyser);
|
11227
|
-
const dataArray = new Uint8Array(analyser.frequencyBinCount);
|
11228
|
-
/**
|
11229
|
-
* Calculates the current volume of the track in the range from 0 to 1
|
11230
|
-
*/
|
11231
|
-
const calculateVolume = () => {
|
11232
|
-
analyser.getByteFrequencyData(dataArray);
|
11233
|
-
let sum = 0;
|
11234
|
-
for (const amplitude of dataArray) {
|
11235
|
-
sum += Math.pow(amplitude / 255, 2);
|
11236
|
-
}
|
11237
|
-
const volume = Math.sqrt(sum / dataArray.length);
|
11238
|
-
return volume;
|
11239
|
-
};
|
11240
|
-
const cleanup = () => {
|
11241
|
-
audioContext.close();
|
11242
|
-
if (opts.cloneTrack) {
|
11243
|
-
streamTrack.stop();
|
11244
|
-
}
|
11245
|
-
};
|
11246
|
-
return {
|
11247
|
-
calculateVolume,
|
11248
|
-
analyser,
|
11249
|
-
cleanup
|
11250
|
-
};
|
11251
|
-
}
|
11252
|
-
class Mutex {
|
11253
|
-
constructor() {
|
11254
|
-
this._locking = Promise.resolve();
|
11255
|
-
this._locks = 0;
|
11256
|
-
}
|
11257
|
-
isLocked() {
|
11258
|
-
return this._locks > 0;
|
11259
|
-
}
|
11260
|
-
lock() {
|
11261
|
-
this._locks += 1;
|
11262
|
-
let unlockNext;
|
11263
|
-
const willLock = new Promise(resolve => unlockNext = () => {
|
11264
|
-
this._locks -= 1;
|
11265
|
-
resolve();
|
11266
|
-
});
|
11267
|
-
const willUnlock = this._locking.then(() => unlockNext);
|
11268
|
-
this._locking = this._locking.then(() => willLock);
|
11269
|
-
return willUnlock;
|
11270
|
-
}
|
11271
|
-
}
|
11272
|
-
|
11273
|
-
var QueueTaskStatus;
|
11274
|
-
(function (QueueTaskStatus) {
|
11275
|
-
QueueTaskStatus[QueueTaskStatus["WAITING"] = 0] = "WAITING";
|
11276
|
-
QueueTaskStatus[QueueTaskStatus["RUNNING"] = 1] = "RUNNING";
|
11277
|
-
QueueTaskStatus[QueueTaskStatus["COMPLETED"] = 2] = "COMPLETED";
|
11278
|
-
})(QueueTaskStatus || (QueueTaskStatus = {}));
|
11279
|
-
class AsyncQueue {
|
11280
|
-
constructor() {
|
11281
|
-
this.pendingTasks = new Map();
|
11282
|
-
this.taskMutex = new Mutex();
|
11283
|
-
this.nextTaskIndex = 0;
|
11284
|
-
}
|
11285
|
-
run(task) {
|
11286
|
-
return __awaiter(this, void 0, void 0, function* () {
|
11287
|
-
const taskInfo = {
|
11288
|
-
id: this.nextTaskIndex++,
|
11289
|
-
enqueuedAt: Date.now(),
|
11290
|
-
status: QueueTaskStatus.WAITING
|
11291
|
-
};
|
11292
|
-
this.pendingTasks.set(taskInfo.id, taskInfo);
|
11293
|
-
const unlock = yield this.taskMutex.lock();
|
11294
|
-
try {
|
11295
|
-
taskInfo.executedAt = Date.now();
|
11296
|
-
taskInfo.status = QueueTaskStatus.RUNNING;
|
11297
|
-
return yield task();
|
11298
|
-
} finally {
|
11299
|
-
taskInfo.status = QueueTaskStatus.COMPLETED;
|
11300
|
-
this.pendingTasks.delete(taskInfo.id);
|
11301
|
-
unlock();
|
11302
|
-
}
|
11303
|
-
});
|
11304
|
-
}
|
11305
|
-
flush() {
|
11306
|
-
return __awaiter(this, void 0, void 0, function* () {
|
11307
|
-
return this.run(() => __awaiter(this, void 0, void 0, function* () {}));
|
11308
|
-
});
|
11309
|
-
}
|
11310
|
-
snapshot() {
|
11311
|
-
return Array.from(this.pendingTasks.values());
|
11312
|
-
}
|
11313
|
-
}
|
11314
|
-
|
11315
|
-
/* eslint-disable */
|
11316
|
-
var SignalTarget;
|
11317
|
-
(function (SignalTarget) {
|
11318
|
-
SignalTarget[SignalTarget["PUBLISHER"] = 0] = "PUBLISHER";
|
11319
|
-
SignalTarget[SignalTarget["SUBSCRIBER"] = 1] = "SUBSCRIBER";
|
11320
|
-
SignalTarget[SignalTarget["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
|
11321
|
-
})(SignalTarget || (SignalTarget = {}));
|
11322
|
-
function signalTargetFromJSON(object) {
|
11323
|
-
switch (object) {
|
11324
|
-
case 0:
|
11325
|
-
case "PUBLISHER":
|
11326
|
-
return SignalTarget.PUBLISHER;
|
11327
|
-
case 1:
|
11328
|
-
case "SUBSCRIBER":
|
11329
|
-
return SignalTarget.SUBSCRIBER;
|
11330
|
-
case -1:
|
11331
|
-
case "UNRECOGNIZED":
|
11332
|
-
default:
|
11333
|
-
return SignalTarget.UNRECOGNIZED;
|
11334
|
-
}
|
11335
|
-
}
|
11336
|
-
function signalTargetToJSON(object) {
|
11337
|
-
switch (object) {
|
11338
|
-
case SignalTarget.PUBLISHER:
|
11339
|
-
return "PUBLISHER";
|
11340
|
-
case SignalTarget.SUBSCRIBER:
|
11341
|
-
return "SUBSCRIBER";
|
11342
|
-
case SignalTarget.UNRECOGNIZED:
|
11343
|
-
default:
|
11344
|
-
return "UNRECOGNIZED";
|
11345
|
-
}
|
11346
|
-
}
|
11347
|
-
var StreamState;
|
11348
|
-
(function (StreamState) {
|
11349
|
-
StreamState[StreamState["ACTIVE"] = 0] = "ACTIVE";
|
11350
|
-
StreamState[StreamState["PAUSED"] = 1] = "PAUSED";
|
11351
|
-
StreamState[StreamState["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
|
11352
|
-
})(StreamState || (StreamState = {}));
|
11353
|
-
function streamStateFromJSON(object) {
|
11354
|
-
switch (object) {
|
11355
|
-
case 0:
|
11356
|
-
case "ACTIVE":
|
11357
|
-
return StreamState.ACTIVE;
|
11358
|
-
case 1:
|
11359
|
-
case "PAUSED":
|
11360
|
-
return StreamState.PAUSED;
|
11361
|
-
case -1:
|
11362
|
-
case "UNRECOGNIZED":
|
11363
|
-
default:
|
11364
|
-
return StreamState.UNRECOGNIZED;
|
11365
|
-
}
|
11366
|
-
}
|
11367
|
-
function streamStateToJSON(object) {
|
11368
|
-
switch (object) {
|
11369
|
-
case StreamState.ACTIVE:
|
11370
|
-
return "ACTIVE";
|
11371
|
-
case StreamState.PAUSED:
|
11372
|
-
return "PAUSED";
|
11373
|
-
case StreamState.UNRECOGNIZED:
|
11374
|
-
default:
|
11375
|
-
return "UNRECOGNIZED";
|
11376
|
-
}
|
11377
|
-
}
|
11378
|
-
var CandidateProtocol;
|
11379
|
-
(function (CandidateProtocol) {
|
11380
|
-
CandidateProtocol[CandidateProtocol["UDP"] = 0] = "UDP";
|
11381
|
-
CandidateProtocol[CandidateProtocol["TCP"] = 1] = "TCP";
|
11382
|
-
CandidateProtocol[CandidateProtocol["TLS"] = 2] = "TLS";
|
11383
|
-
CandidateProtocol[CandidateProtocol["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
|
11384
|
-
})(CandidateProtocol || (CandidateProtocol = {}));
|
11385
|
-
function candidateProtocolFromJSON(object) {
|
11386
|
-
switch (object) {
|
11387
|
-
case 0:
|
11388
|
-
case "UDP":
|
11389
|
-
return CandidateProtocol.UDP;
|
11390
|
-
case 1:
|
11391
|
-
case "TCP":
|
11392
|
-
return CandidateProtocol.TCP;
|
11393
|
-
case 2:
|
11394
|
-
case "TLS":
|
11395
|
-
return CandidateProtocol.TLS;
|
11396
|
-
case -1:
|
11397
|
-
case "UNRECOGNIZED":
|
11398
|
-
default:
|
11399
|
-
return CandidateProtocol.UNRECOGNIZED;
|
11400
|
-
}
|
11401
|
-
}
|
11402
|
-
function candidateProtocolToJSON(object) {
|
11403
|
-
switch (object) {
|
11404
|
-
case CandidateProtocol.UDP:
|
11405
|
-
return "UDP";
|
11406
|
-
case CandidateProtocol.TCP:
|
11407
|
-
return "TCP";
|
11408
|
-
case CandidateProtocol.TLS:
|
11409
|
-
return "TLS";
|
11410
|
-
case CandidateProtocol.UNRECOGNIZED:
|
11411
|
-
default:
|
11412
|
-
return "UNRECOGNIZED";
|
11413
|
-
}
|
11414
|
-
}
|
11415
|
-
function createBaseSignalRequest() {
|
11416
|
-
return {
|
11417
|
-
message: undefined
|
11418
|
-
};
|
10193
|
+
function createBaseSignalRequest() {
|
10194
|
+
return {
|
10195
|
+
message: undefined
|
10196
|
+
};
|
11419
10197
|
}
|
11420
10198
|
const SignalRequest = {
|
11421
10199
|
encode(message) {
|
@@ -14965,263 +13743,809 @@ const SimulateScenario = {
|
|
14965
13743
|
subscriberBandwidth: object.scenario.subscriberBandwidth
|
14966
13744
|
};
|
14967
13745
|
}
|
14968
|
-
return message;
|
13746
|
+
return message;
|
13747
|
+
}
|
13748
|
+
};
|
13749
|
+
function createBasePing() {
|
13750
|
+
return {
|
13751
|
+
timestamp: 0,
|
13752
|
+
rtt: 0
|
13753
|
+
};
|
13754
|
+
}
|
13755
|
+
const Ping = {
|
13756
|
+
encode(message) {
|
13757
|
+
let writer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _m0.Writer.create();
|
13758
|
+
if (message.timestamp !== 0) {
|
13759
|
+
writer.uint32(8).int64(message.timestamp);
|
13760
|
+
}
|
13761
|
+
if (message.rtt !== 0) {
|
13762
|
+
writer.uint32(16).int64(message.rtt);
|
13763
|
+
}
|
13764
|
+
return writer;
|
13765
|
+
},
|
13766
|
+
decode(input, length) {
|
13767
|
+
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
13768
|
+
let end = length === undefined ? reader.len : reader.pos + length;
|
13769
|
+
const message = createBasePing();
|
13770
|
+
while (reader.pos < end) {
|
13771
|
+
const tag = reader.uint32();
|
13772
|
+
switch (tag >>> 3) {
|
13773
|
+
case 1:
|
13774
|
+
if (tag != 8) {
|
13775
|
+
break;
|
13776
|
+
}
|
13777
|
+
message.timestamp = longToNumber(reader.int64());
|
13778
|
+
continue;
|
13779
|
+
case 2:
|
13780
|
+
if (tag != 16) {
|
13781
|
+
break;
|
13782
|
+
}
|
13783
|
+
message.rtt = longToNumber(reader.int64());
|
13784
|
+
continue;
|
13785
|
+
}
|
13786
|
+
if ((tag & 7) == 4 || tag == 0) {
|
13787
|
+
break;
|
13788
|
+
}
|
13789
|
+
reader.skipType(tag & 7);
|
13790
|
+
}
|
13791
|
+
return message;
|
13792
|
+
},
|
13793
|
+
fromJSON(object) {
|
13794
|
+
return {
|
13795
|
+
timestamp: isSet(object.timestamp) ? Number(object.timestamp) : 0,
|
13796
|
+
rtt: isSet(object.rtt) ? Number(object.rtt) : 0
|
13797
|
+
};
|
13798
|
+
},
|
13799
|
+
toJSON(message) {
|
13800
|
+
const obj = {};
|
13801
|
+
message.timestamp !== undefined && (obj.timestamp = Math.round(message.timestamp));
|
13802
|
+
message.rtt !== undefined && (obj.rtt = Math.round(message.rtt));
|
13803
|
+
return obj;
|
13804
|
+
},
|
13805
|
+
create(base) {
|
13806
|
+
return Ping.fromPartial(base !== null && base !== void 0 ? base : {});
|
13807
|
+
},
|
13808
|
+
fromPartial(object) {
|
13809
|
+
var _a, _b;
|
13810
|
+
const message = createBasePing();
|
13811
|
+
message.timestamp = (_a = object.timestamp) !== null && _a !== void 0 ? _a : 0;
|
13812
|
+
message.rtt = (_b = object.rtt) !== null && _b !== void 0 ? _b : 0;
|
13813
|
+
return message;
|
13814
|
+
}
|
13815
|
+
};
|
13816
|
+
function createBasePong() {
|
13817
|
+
return {
|
13818
|
+
lastPingTimestamp: 0,
|
13819
|
+
timestamp: 0
|
13820
|
+
};
|
13821
|
+
}
|
13822
|
+
const Pong = {
|
13823
|
+
encode(message) {
|
13824
|
+
let writer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _m0.Writer.create();
|
13825
|
+
if (message.lastPingTimestamp !== 0) {
|
13826
|
+
writer.uint32(8).int64(message.lastPingTimestamp);
|
13827
|
+
}
|
13828
|
+
if (message.timestamp !== 0) {
|
13829
|
+
writer.uint32(16).int64(message.timestamp);
|
13830
|
+
}
|
13831
|
+
return writer;
|
13832
|
+
},
|
13833
|
+
decode(input, length) {
|
13834
|
+
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
13835
|
+
let end = length === undefined ? reader.len : reader.pos + length;
|
13836
|
+
const message = createBasePong();
|
13837
|
+
while (reader.pos < end) {
|
13838
|
+
const tag = reader.uint32();
|
13839
|
+
switch (tag >>> 3) {
|
13840
|
+
case 1:
|
13841
|
+
if (tag != 8) {
|
13842
|
+
break;
|
13843
|
+
}
|
13844
|
+
message.lastPingTimestamp = longToNumber(reader.int64());
|
13845
|
+
continue;
|
13846
|
+
case 2:
|
13847
|
+
if (tag != 16) {
|
13848
|
+
break;
|
13849
|
+
}
|
13850
|
+
message.timestamp = longToNumber(reader.int64());
|
13851
|
+
continue;
|
13852
|
+
}
|
13853
|
+
if ((tag & 7) == 4 || tag == 0) {
|
13854
|
+
break;
|
13855
|
+
}
|
13856
|
+
reader.skipType(tag & 7);
|
13857
|
+
}
|
13858
|
+
return message;
|
13859
|
+
},
|
13860
|
+
fromJSON(object) {
|
13861
|
+
return {
|
13862
|
+
lastPingTimestamp: isSet(object.lastPingTimestamp) ? Number(object.lastPingTimestamp) : 0,
|
13863
|
+
timestamp: isSet(object.timestamp) ? Number(object.timestamp) : 0
|
13864
|
+
};
|
13865
|
+
},
|
13866
|
+
toJSON(message) {
|
13867
|
+
const obj = {};
|
13868
|
+
message.lastPingTimestamp !== undefined && (obj.lastPingTimestamp = Math.round(message.lastPingTimestamp));
|
13869
|
+
message.timestamp !== undefined && (obj.timestamp = Math.round(message.timestamp));
|
13870
|
+
return obj;
|
13871
|
+
},
|
13872
|
+
create(base) {
|
13873
|
+
return Pong.fromPartial(base !== null && base !== void 0 ? base : {});
|
13874
|
+
},
|
13875
|
+
fromPartial(object) {
|
13876
|
+
var _a, _b;
|
13877
|
+
const message = createBasePong();
|
13878
|
+
message.lastPingTimestamp = (_a = object.lastPingTimestamp) !== null && _a !== void 0 ? _a : 0;
|
13879
|
+
message.timestamp = (_b = object.timestamp) !== null && _b !== void 0 ? _b : 0;
|
13880
|
+
return message;
|
13881
|
+
}
|
13882
|
+
};
|
13883
|
+
var tsProtoGlobalThis = (() => {
|
13884
|
+
if (typeof globalThis !== "undefined") {
|
13885
|
+
return globalThis;
|
13886
|
+
}
|
13887
|
+
if (typeof self !== "undefined") {
|
13888
|
+
return self;
|
13889
|
+
}
|
13890
|
+
if (typeof window !== "undefined") {
|
13891
|
+
return window;
|
13892
|
+
}
|
13893
|
+
if (typeof global !== "undefined") {
|
13894
|
+
return global;
|
13895
|
+
}
|
13896
|
+
throw "Unable to locate global object";
|
13897
|
+
})();
|
13898
|
+
function longToNumber(long) {
|
13899
|
+
if (long.gt(Number.MAX_SAFE_INTEGER)) {
|
13900
|
+
throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
|
13901
|
+
}
|
13902
|
+
return long.toNumber();
|
13903
|
+
}
|
13904
|
+
if (_m0.util.Long !== Long$1) {
|
13905
|
+
_m0.util.Long = Long$1;
|
13906
|
+
_m0.configure();
|
13907
|
+
}
|
13908
|
+
function isSet(value) {
|
13909
|
+
return value !== null && value !== undefined;
|
13910
|
+
}
|
13911
|
+
|
13912
|
+
class LivekitError extends Error {
|
13913
|
+
constructor(code, message) {
|
13914
|
+
super(message || 'an error has occured');
|
13915
|
+
this.code = code;
|
13916
|
+
}
|
13917
|
+
}
|
13918
|
+
class ConnectionError extends LivekitError {
|
13919
|
+
constructor(message, reason, status) {
|
13920
|
+
super(1, message);
|
13921
|
+
this.status = status;
|
13922
|
+
this.reason = reason;
|
13923
|
+
}
|
13924
|
+
}
|
13925
|
+
class DeviceUnsupportedError extends LivekitError {
|
13926
|
+
constructor(message) {
|
13927
|
+
super(21, message !== null && message !== void 0 ? message : 'device is unsupported');
|
13928
|
+
}
|
13929
|
+
}
|
13930
|
+
class TrackInvalidError extends LivekitError {
|
13931
|
+
constructor(message) {
|
13932
|
+
super(20, message !== null && message !== void 0 ? message : 'track is invalid');
|
13933
|
+
}
|
13934
|
+
}
|
13935
|
+
class UnsupportedServer extends LivekitError {
|
13936
|
+
constructor(message) {
|
13937
|
+
super(10, message !== null && message !== void 0 ? message : 'unsupported server');
|
13938
|
+
}
|
13939
|
+
}
|
13940
|
+
class UnexpectedConnectionState extends LivekitError {
|
13941
|
+
constructor(message) {
|
13942
|
+
super(12, message !== null && message !== void 0 ? message : 'unexpected connection state');
|
13943
|
+
}
|
13944
|
+
}
|
13945
|
+
class NegotiationError extends LivekitError {
|
13946
|
+
constructor(message) {
|
13947
|
+
super(13, message !== null && message !== void 0 ? message : 'unable to negotiate');
|
13948
|
+
}
|
13949
|
+
}
|
13950
|
+
class PublishDataError extends LivekitError {
|
13951
|
+
constructor(message) {
|
13952
|
+
super(13, message !== null && message !== void 0 ? message : 'unable to publish data');
|
13953
|
+
}
|
13954
|
+
}
|
13955
|
+
var MediaDeviceFailure;
|
13956
|
+
(function (MediaDeviceFailure) {
|
13957
|
+
// user rejected permissions
|
13958
|
+
MediaDeviceFailure["PermissionDenied"] = "PermissionDenied";
|
13959
|
+
// device is not available
|
13960
|
+
MediaDeviceFailure["NotFound"] = "NotFound";
|
13961
|
+
// device is in use. On Windows, only a single tab may get access to a device at a time.
|
13962
|
+
MediaDeviceFailure["DeviceInUse"] = "DeviceInUse";
|
13963
|
+
MediaDeviceFailure["Other"] = "Other";
|
13964
|
+
})(MediaDeviceFailure || (MediaDeviceFailure = {}));
|
13965
|
+
(function (MediaDeviceFailure) {
|
13966
|
+
function getFailure(error) {
|
13967
|
+
if (error && 'name' in error) {
|
13968
|
+
if (error.name === 'NotFoundError' || error.name === 'DevicesNotFoundError') {
|
13969
|
+
return MediaDeviceFailure.NotFound;
|
13970
|
+
}
|
13971
|
+
if (error.name === 'NotAllowedError' || error.name === 'PermissionDeniedError') {
|
13972
|
+
return MediaDeviceFailure.PermissionDenied;
|
13973
|
+
}
|
13974
|
+
if (error.name === 'NotReadableError' || error.name === 'TrackStartError') {
|
13975
|
+
return MediaDeviceFailure.DeviceInUse;
|
13976
|
+
}
|
13977
|
+
return MediaDeviceFailure.Other;
|
13978
|
+
}
|
14969
13979
|
}
|
13980
|
+
MediaDeviceFailure.getFailure = getFailure;
|
13981
|
+
})(MediaDeviceFailure || (MediaDeviceFailure = {}));
|
13982
|
+
|
13983
|
+
/**
|
13984
|
+
* Timers that can be overridden with platform specific implementations
|
13985
|
+
* that ensure that they are fired. These should be used when it is critical
|
13986
|
+
* that the timer fires on time.
|
13987
|
+
*/
|
13988
|
+
class CriticalTimers {}
|
13989
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
13990
|
+
CriticalTimers.setTimeout = function () {
|
13991
|
+
return setTimeout(...arguments);
|
14970
13992
|
};
|
14971
|
-
|
14972
|
-
|
14973
|
-
|
14974
|
-
|
14975
|
-
|
13993
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
13994
|
+
CriticalTimers.setInterval = function () {
|
13995
|
+
return setInterval(...arguments);
|
13996
|
+
};
|
13997
|
+
CriticalTimers.clearTimeout = function () {
|
13998
|
+
return clearTimeout(...arguments);
|
13999
|
+
};
|
14000
|
+
CriticalTimers.clearInterval = function () {
|
14001
|
+
return clearInterval(...arguments);
|
14002
|
+
};
|
14003
|
+
|
14004
|
+
// tiny, simplified version of https://github.com/lancedikson/bowser/blob/master/src/parser-browsers.js
|
14005
|
+
// reduced to only differentiate Chrome(ium) based browsers / Firefox / Safari
|
14006
|
+
const commonVersionIdentifier = /version\/(\d+(\.?_?\d+)+)/i;
|
14007
|
+
let browserDetails;
|
14008
|
+
/**
|
14009
|
+
* @internal
|
14010
|
+
*/
|
14011
|
+
function getBrowser(userAgent) {
|
14012
|
+
let force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
14013
|
+
if (userAgent === undefined && (typeof document !== 'undefined' || typeof navigator === 'undefined')) {
|
14014
|
+
return;
|
14015
|
+
}
|
14016
|
+
const ua = (userAgent !== null && userAgent !== void 0 ? userAgent : navigator.userAgent).toLowerCase();
|
14017
|
+
if (browserDetails === undefined || force) {
|
14018
|
+
const browser = browsersList.find(_ref => {
|
14019
|
+
let {
|
14020
|
+
test
|
14021
|
+
} = _ref;
|
14022
|
+
return test.test(ua);
|
14023
|
+
});
|
14024
|
+
browserDetails = browser === null || browser === void 0 ? void 0 : browser.describe(ua);
|
14025
|
+
}
|
14026
|
+
return browserDetails;
|
14976
14027
|
}
|
14977
|
-
const
|
14978
|
-
|
14979
|
-
|
14980
|
-
|
14981
|
-
|
14028
|
+
const browsersList = [{
|
14029
|
+
test: /firefox|iceweasel|fxios/i,
|
14030
|
+
describe(ua) {
|
14031
|
+
const browser = {
|
14032
|
+
name: 'Firefox',
|
14033
|
+
version: getMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i, ua)
|
14034
|
+
};
|
14035
|
+
return browser;
|
14036
|
+
}
|
14037
|
+
}, {
|
14038
|
+
test: /chrom|crios|crmo/i,
|
14039
|
+
describe(ua) {
|
14040
|
+
const browser = {
|
14041
|
+
name: 'Chrome',
|
14042
|
+
version: getMatch(/(?:chrome|chromium|crios|crmo)\/(\d+(\.?_?\d+)+)/i, ua)
|
14043
|
+
};
|
14044
|
+
return browser;
|
14045
|
+
}
|
14046
|
+
}, /* Safari */
|
14047
|
+
{
|
14048
|
+
test: /safari|applewebkit/i,
|
14049
|
+
describe(ua) {
|
14050
|
+
const browser = {
|
14051
|
+
name: 'Safari',
|
14052
|
+
version: getMatch(commonVersionIdentifier, ua)
|
14053
|
+
};
|
14054
|
+
return browser;
|
14055
|
+
}
|
14056
|
+
}];
|
14057
|
+
function getMatch(exp, ua) {
|
14058
|
+
let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
|
14059
|
+
const match = ua.match(exp);
|
14060
|
+
return match && match.length >= id && match[id] || '';
|
14061
|
+
}
|
14062
|
+
|
14063
|
+
var version$1 = "1.9.5";
|
14064
|
+
|
14065
|
+
const version = version$1;
|
14066
|
+
const protocolVersion = 9;
|
14067
|
+
|
14068
|
+
function mergeDefaultOptions(options, audioDefaults, videoDefaults) {
|
14069
|
+
const opts = Object.assign({}, options);
|
14070
|
+
if (opts.audio === true) opts.audio = {};
|
14071
|
+
if (opts.video === true) opts.video = {};
|
14072
|
+
// use defaults
|
14073
|
+
if (opts.audio) {
|
14074
|
+
mergeObjectWithoutOverwriting(opts.audio, audioDefaults);
|
14075
|
+
}
|
14076
|
+
if (opts.video) {
|
14077
|
+
mergeObjectWithoutOverwriting(opts.video, videoDefaults);
|
14078
|
+
}
|
14079
|
+
return opts;
|
14080
|
+
}
|
14081
|
+
function mergeObjectWithoutOverwriting(mainObject, objectToMerge) {
|
14082
|
+
Object.keys(objectToMerge).forEach(key => {
|
14083
|
+
if (mainObject[key] === undefined) mainObject[key] = objectToMerge[key];
|
14084
|
+
});
|
14085
|
+
return mainObject;
|
14086
|
+
}
|
14087
|
+
function constraintsForOptions(options) {
|
14088
|
+
const constraints = {};
|
14089
|
+
if (options.video) {
|
14090
|
+
// default video options
|
14091
|
+
if (typeof options.video === 'object') {
|
14092
|
+
const videoOptions = {};
|
14093
|
+
const target = videoOptions;
|
14094
|
+
const source = options.video;
|
14095
|
+
Object.keys(source).forEach(key => {
|
14096
|
+
switch (key) {
|
14097
|
+
case 'resolution':
|
14098
|
+
// flatten VideoResolution fields
|
14099
|
+
mergeObjectWithoutOverwriting(target, source.resolution);
|
14100
|
+
break;
|
14101
|
+
default:
|
14102
|
+
target[key] = source[key];
|
14103
|
+
}
|
14104
|
+
});
|
14105
|
+
constraints.video = videoOptions;
|
14106
|
+
} else {
|
14107
|
+
constraints.video = options.video;
|
14982
14108
|
}
|
14983
|
-
|
14984
|
-
|
14109
|
+
} else {
|
14110
|
+
constraints.video = false;
|
14111
|
+
}
|
14112
|
+
if (options.audio) {
|
14113
|
+
if (typeof options.audio === 'object') {
|
14114
|
+
constraints.audio = options.audio;
|
14115
|
+
} else {
|
14116
|
+
constraints.audio = true;
|
14985
14117
|
}
|
14986
|
-
|
14987
|
-
|
14988
|
-
|
14989
|
-
|
14990
|
-
|
14991
|
-
|
14992
|
-
|
14993
|
-
|
14994
|
-
|
14995
|
-
|
14996
|
-
|
14997
|
-
|
14998
|
-
|
14999
|
-
|
15000
|
-
|
15001
|
-
|
15002
|
-
|
15003
|
-
|
15004
|
-
|
15005
|
-
|
15006
|
-
|
15007
|
-
|
15008
|
-
|
14118
|
+
} else {
|
14119
|
+
constraints.audio = false;
|
14120
|
+
}
|
14121
|
+
return constraints;
|
14122
|
+
}
|
14123
|
+
/**
|
14124
|
+
* This function detects silence on a given [[Track]] instance.
|
14125
|
+
* Returns true if the track seems to be entirely silent.
|
14126
|
+
*/
|
14127
|
+
function detectSilence(track) {
|
14128
|
+
let timeOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
|
14129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
14130
|
+
const ctx = getNewAudioContext();
|
14131
|
+
if (ctx) {
|
14132
|
+
const analyser = ctx.createAnalyser();
|
14133
|
+
analyser.fftSize = 2048;
|
14134
|
+
const bufferLength = analyser.frequencyBinCount;
|
14135
|
+
const dataArray = new Uint8Array(bufferLength);
|
14136
|
+
const source = ctx.createMediaStreamSource(new MediaStream([track.mediaStreamTrack]));
|
14137
|
+
source.connect(analyser);
|
14138
|
+
yield sleep(timeOffset);
|
14139
|
+
analyser.getByteTimeDomainData(dataArray);
|
14140
|
+
const someNoise = dataArray.some(sample => sample !== 128 && sample !== 0);
|
14141
|
+
ctx.close();
|
14142
|
+
return !someNoise;
|
14143
|
+
}
|
14144
|
+
return false;
|
14145
|
+
});
|
14146
|
+
}
|
14147
|
+
/**
|
14148
|
+
* @internal
|
14149
|
+
*/
|
14150
|
+
function getNewAudioContext() {
|
14151
|
+
const AudioContext =
|
14152
|
+
// @ts-ignore
|
14153
|
+
typeof window !== 'undefined' && (window.AudioContext || window.webkitAudioContext);
|
14154
|
+
if (AudioContext) {
|
14155
|
+
return new AudioContext({
|
14156
|
+
latencyHint: 'interactive'
|
14157
|
+
});
|
14158
|
+
}
|
14159
|
+
}
|
14160
|
+
|
14161
|
+
const separator = '|';
|
14162
|
+
const ddExtensionURI = 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension';
|
14163
|
+
function unpackStreamId(packed) {
|
14164
|
+
const parts = packed.split(separator);
|
14165
|
+
if (parts.length > 1) {
|
14166
|
+
return [parts[0], packed.substr(parts[0].length + 1)];
|
14167
|
+
}
|
14168
|
+
return [packed, ''];
|
14169
|
+
}
|
14170
|
+
function sleep(duration) {
|
14171
|
+
return __awaiter(this, void 0, void 0, function* () {
|
14172
|
+
return new Promise(resolve => setTimeout(resolve, duration));
|
14173
|
+
});
|
14174
|
+
}
|
14175
|
+
/** @internal */
|
14176
|
+
function supportsTransceiver() {
|
14177
|
+
return 'addTransceiver' in RTCPeerConnection.prototype;
|
14178
|
+
}
|
14179
|
+
/** @internal */
|
14180
|
+
function supportsAddTrack() {
|
14181
|
+
return 'addTrack' in RTCPeerConnection.prototype;
|
14182
|
+
}
|
14183
|
+
function supportsAdaptiveStream() {
|
14184
|
+
return typeof ResizeObserver !== undefined && typeof IntersectionObserver !== undefined;
|
14185
|
+
}
|
14186
|
+
function supportsDynacast() {
|
14187
|
+
return supportsTransceiver();
|
14188
|
+
}
|
14189
|
+
function supportsAV1() {
|
14190
|
+
if (!('getCapabilities' in RTCRtpSender)) {
|
14191
|
+
return false;
|
14192
|
+
}
|
14193
|
+
const capabilities = RTCRtpSender.getCapabilities('video');
|
14194
|
+
let hasAV1 = false;
|
14195
|
+
if (capabilities) {
|
14196
|
+
for (const codec of capabilities.codecs) {
|
14197
|
+
if (codec.mimeType === 'video/AV1') {
|
14198
|
+
hasAV1 = true;
|
15009
14199
|
break;
|
15010
14200
|
}
|
15011
|
-
reader.skipType(tag & 7);
|
15012
14201
|
}
|
15013
|
-
return message;
|
15014
|
-
},
|
15015
|
-
fromJSON(object) {
|
15016
|
-
return {
|
15017
|
-
timestamp: isSet(object.timestamp) ? Number(object.timestamp) : 0,
|
15018
|
-
rtt: isSet(object.rtt) ? Number(object.rtt) : 0
|
15019
|
-
};
|
15020
|
-
},
|
15021
|
-
toJSON(message) {
|
15022
|
-
const obj = {};
|
15023
|
-
message.timestamp !== undefined && (obj.timestamp = Math.round(message.timestamp));
|
15024
|
-
message.rtt !== undefined && (obj.rtt = Math.round(message.rtt));
|
15025
|
-
return obj;
|
15026
|
-
},
|
15027
|
-
create(base) {
|
15028
|
-
return Ping.fromPartial(base !== null && base !== void 0 ? base : {});
|
15029
|
-
},
|
15030
|
-
fromPartial(object) {
|
15031
|
-
var _a, _b;
|
15032
|
-
const message = createBasePing();
|
15033
|
-
message.timestamp = (_a = object.timestamp) !== null && _a !== void 0 ? _a : 0;
|
15034
|
-
message.rtt = (_b = object.rtt) !== null && _b !== void 0 ? _b : 0;
|
15035
|
-
return message;
|
15036
14202
|
}
|
15037
|
-
|
15038
|
-
function createBasePong() {
|
15039
|
-
return {
|
15040
|
-
lastPingTimestamp: 0,
|
15041
|
-
timestamp: 0
|
15042
|
-
};
|
14203
|
+
return hasAV1;
|
15043
14204
|
}
|
15044
|
-
|
15045
|
-
|
15046
|
-
|
15047
|
-
|
15048
|
-
|
15049
|
-
|
15050
|
-
|
15051
|
-
|
15052
|
-
|
15053
|
-
|
15054
|
-
|
15055
|
-
|
15056
|
-
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
15057
|
-
let end = length === undefined ? reader.len : reader.pos + length;
|
15058
|
-
const message = createBasePong();
|
15059
|
-
while (reader.pos < end) {
|
15060
|
-
const tag = reader.uint32();
|
15061
|
-
switch (tag >>> 3) {
|
15062
|
-
case 1:
|
15063
|
-
if (tag != 8) {
|
15064
|
-
break;
|
15065
|
-
}
|
15066
|
-
message.lastPingTimestamp = longToNumber(reader.int64());
|
15067
|
-
continue;
|
15068
|
-
case 2:
|
15069
|
-
if (tag != 16) {
|
15070
|
-
break;
|
15071
|
-
}
|
15072
|
-
message.timestamp = longToNumber(reader.int64());
|
15073
|
-
continue;
|
15074
|
-
}
|
15075
|
-
if ((tag & 7) == 4 || tag == 0) {
|
14205
|
+
function supportsVP9() {
|
14206
|
+
if (!('getCapabilities' in RTCRtpSender)) {
|
14207
|
+
// technically speaking FireFox supports VP9, but SVC publishing is broken
|
14208
|
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=1633876
|
14209
|
+
return false;
|
14210
|
+
}
|
14211
|
+
const capabilities = RTCRtpSender.getCapabilities('video');
|
14212
|
+
let hasVP9 = false;
|
14213
|
+
if (capabilities) {
|
14214
|
+
for (const codec of capabilities.codecs) {
|
14215
|
+
if (codec.mimeType === 'video/VP9') {
|
14216
|
+
hasVP9 = true;
|
15076
14217
|
break;
|
15077
14218
|
}
|
15078
|
-
reader.skipType(tag & 7);
|
15079
14219
|
}
|
15080
|
-
return message;
|
15081
|
-
},
|
15082
|
-
fromJSON(object) {
|
15083
|
-
return {
|
15084
|
-
lastPingTimestamp: isSet(object.lastPingTimestamp) ? Number(object.lastPingTimestamp) : 0,
|
15085
|
-
timestamp: isSet(object.timestamp) ? Number(object.timestamp) : 0
|
15086
|
-
};
|
15087
|
-
},
|
15088
|
-
toJSON(message) {
|
15089
|
-
const obj = {};
|
15090
|
-
message.lastPingTimestamp !== undefined && (obj.lastPingTimestamp = Math.round(message.lastPingTimestamp));
|
15091
|
-
message.timestamp !== undefined && (obj.timestamp = Math.round(message.timestamp));
|
15092
|
-
return obj;
|
15093
|
-
},
|
15094
|
-
create(base) {
|
15095
|
-
return Pong.fromPartial(base !== null && base !== void 0 ? base : {});
|
15096
|
-
},
|
15097
|
-
fromPartial(object) {
|
15098
|
-
var _a, _b;
|
15099
|
-
const message = createBasePong();
|
15100
|
-
message.lastPingTimestamp = (_a = object.lastPingTimestamp) !== null && _a !== void 0 ? _a : 0;
|
15101
|
-
message.timestamp = (_b = object.timestamp) !== null && _b !== void 0 ? _b : 0;
|
15102
|
-
return message;
|
15103
14220
|
}
|
14221
|
+
return hasVP9;
|
14222
|
+
}
|
14223
|
+
function isSVCCodec(codec) {
|
14224
|
+
return codec === 'av1' || codec === 'vp9';
|
14225
|
+
}
|
14226
|
+
function supportsSetSinkId(elm) {
|
14227
|
+
if (!document) {
|
14228
|
+
return false;
|
14229
|
+
}
|
14230
|
+
if (!elm) {
|
14231
|
+
elm = document.createElement('audio');
|
14232
|
+
}
|
14233
|
+
return 'setSinkId' in elm;
|
14234
|
+
}
|
14235
|
+
const setCodecPreferencesVersions = {
|
14236
|
+
Chrome: '100',
|
14237
|
+
Safari: '15',
|
14238
|
+
Firefox: '100'
|
15104
14239
|
};
|
15105
|
-
|
15106
|
-
if (
|
15107
|
-
return
|
14240
|
+
function supportsSetCodecPreferences(transceiver) {
|
14241
|
+
if (!isWeb()) {
|
14242
|
+
return false;
|
15108
14243
|
}
|
15109
|
-
if (
|
15110
|
-
return
|
14244
|
+
if (!('setCodecPreferences' in transceiver)) {
|
14245
|
+
return false;
|
15111
14246
|
}
|
15112
|
-
|
15113
|
-
|
14247
|
+
const browser = getBrowser();
|
14248
|
+
if (!(browser === null || browser === void 0 ? void 0 : browser.name) || !browser.version) {
|
14249
|
+
// version is required
|
14250
|
+
return false;
|
15114
14251
|
}
|
15115
|
-
|
15116
|
-
|
14252
|
+
const v = setCodecPreferencesVersions[browser.name];
|
14253
|
+
if (v) {
|
14254
|
+
return compareVersions(browser.version, v) >= 0;
|
15117
14255
|
}
|
15118
|
-
|
15119
|
-
}
|
15120
|
-
function
|
15121
|
-
|
15122
|
-
|
14256
|
+
return false;
|
14257
|
+
}
|
14258
|
+
function isBrowserSupported() {
|
14259
|
+
return supportsTransceiver() || supportsAddTrack();
|
14260
|
+
}
|
14261
|
+
function isFireFox() {
|
14262
|
+
var _a;
|
14263
|
+
return ((_a = getBrowser()) === null || _a === void 0 ? void 0 : _a.name) === 'Firefox';
|
14264
|
+
}
|
14265
|
+
function isChromiumBased() {
|
14266
|
+
var _a;
|
14267
|
+
return ((_a = getBrowser()) === null || _a === void 0 ? void 0 : _a.name) === 'Chrome';
|
14268
|
+
}
|
14269
|
+
function isSafari() {
|
14270
|
+
var _a;
|
14271
|
+
return ((_a = getBrowser()) === null || _a === void 0 ? void 0 : _a.name) === 'Safari';
|
14272
|
+
}
|
14273
|
+
function isMobile() {
|
14274
|
+
if (!isWeb()) return false;
|
14275
|
+
return /Tablet|iPad|Mobile|Android|BlackBerry/.test(navigator.userAgent);
|
14276
|
+
}
|
14277
|
+
function isWeb() {
|
14278
|
+
return typeof document !== 'undefined';
|
14279
|
+
}
|
14280
|
+
function isReactNative() {
|
14281
|
+
// navigator.product is deprecated on browsers, but will be set appropriately for react-native.
|
14282
|
+
return navigator.product == 'ReactNative';
|
14283
|
+
}
|
14284
|
+
function isCloud(serverUrl) {
|
14285
|
+
return serverUrl.hostname.endsWith('.livekit.cloud');
|
14286
|
+
}
|
14287
|
+
function getLKReactNativeInfo() {
|
14288
|
+
// global defined only for ReactNative.
|
14289
|
+
// @ts-ignore
|
14290
|
+
if (global && global.LiveKitReactNativeGlobal) {
|
14291
|
+
// @ts-ignore
|
14292
|
+
return global.LiveKitReactNativeGlobal;
|
14293
|
+
}
|
14294
|
+
return undefined;
|
14295
|
+
}
|
14296
|
+
function getReactNativeOs() {
|
14297
|
+
if (!isReactNative()) {
|
14298
|
+
return undefined;
|
14299
|
+
}
|
14300
|
+
let info = getLKReactNativeInfo();
|
14301
|
+
if (info) {
|
14302
|
+
return info.platform;
|
14303
|
+
}
|
14304
|
+
return undefined;
|
14305
|
+
}
|
14306
|
+
function getDevicePixelRatio() {
|
14307
|
+
if (isWeb()) {
|
14308
|
+
return window.devicePixelRatio;
|
14309
|
+
}
|
14310
|
+
if (isReactNative()) {
|
14311
|
+
let info = getLKReactNativeInfo();
|
14312
|
+
if (info) {
|
14313
|
+
return info.devicePixelRatio;
|
14314
|
+
}
|
14315
|
+
}
|
14316
|
+
return 1;
|
14317
|
+
}
|
14318
|
+
function compareVersions(v1, v2) {
|
14319
|
+
const parts1 = v1.split('.');
|
14320
|
+
const parts2 = v2.split('.');
|
14321
|
+
const k = Math.min(parts1.length, parts2.length);
|
14322
|
+
for (let i = 0; i < k; ++i) {
|
14323
|
+
const p1 = parseInt(parts1[i], 10);
|
14324
|
+
const p2 = parseInt(parts2[i], 10);
|
14325
|
+
if (p1 > p2) return 1;
|
14326
|
+
if (p1 < p2) return -1;
|
14327
|
+
if (i === k - 1 && p1 === p2) return 0;
|
14328
|
+
}
|
14329
|
+
if (v1 === '' && v2 !== '') {
|
14330
|
+
return -1;
|
14331
|
+
} else if (v2 === '') {
|
14332
|
+
return 1;
|
14333
|
+
}
|
14334
|
+
return parts1.length == parts2.length ? 0 : parts1.length < parts2.length ? -1 : 1;
|
14335
|
+
}
|
14336
|
+
function roDispatchCallback(entries) {
|
14337
|
+
for (const entry of entries) {
|
14338
|
+
entry.target.handleResize(entry);
|
14339
|
+
}
|
14340
|
+
}
|
14341
|
+
function ioDispatchCallback(entries) {
|
14342
|
+
for (const entry of entries) {
|
14343
|
+
entry.target.handleVisibilityChanged(entry);
|
14344
|
+
}
|
14345
|
+
}
|
14346
|
+
let resizeObserver = null;
|
14347
|
+
const getResizeObserver = () => {
|
14348
|
+
if (!resizeObserver) resizeObserver = new ResizeObserver(roDispatchCallback);
|
14349
|
+
return resizeObserver;
|
14350
|
+
};
|
14351
|
+
let intersectionObserver = null;
|
14352
|
+
const getIntersectionObserver = () => {
|
14353
|
+
if (!intersectionObserver) intersectionObserver = new IntersectionObserver(ioDispatchCallback, {
|
14354
|
+
root: document,
|
14355
|
+
rootMargin: '0px'
|
14356
|
+
});
|
14357
|
+
return intersectionObserver;
|
14358
|
+
};
|
14359
|
+
function getClientInfo() {
|
14360
|
+
var _a;
|
14361
|
+
const info = ClientInfo.fromPartial({
|
14362
|
+
sdk: ClientInfo_SDK.JS,
|
14363
|
+
protocol: protocolVersion,
|
14364
|
+
version
|
14365
|
+
});
|
14366
|
+
if (isReactNative()) {
|
14367
|
+
info.os = (_a = getReactNativeOs()) !== null && _a !== void 0 ? _a : '';
|
15123
14368
|
}
|
15124
|
-
return
|
15125
|
-
}
|
15126
|
-
if (_m0.util.Long !== Long$1) {
|
15127
|
-
_m0.util.Long = Long$1;
|
15128
|
-
_m0.configure();
|
15129
|
-
}
|
15130
|
-
function isSet(value) {
|
15131
|
-
return value !== null && value !== undefined;
|
14369
|
+
return info;
|
15132
14370
|
}
|
15133
|
-
|
15134
|
-
|
15135
|
-
|
15136
|
-
|
15137
|
-
this.code = code;
|
14371
|
+
let emptyVideoStreamTrack;
|
14372
|
+
function getEmptyVideoStreamTrack() {
|
14373
|
+
if (!emptyVideoStreamTrack) {
|
14374
|
+
emptyVideoStreamTrack = createDummyVideoStreamTrack();
|
15138
14375
|
}
|
14376
|
+
return emptyVideoStreamTrack;
|
15139
14377
|
}
|
15140
|
-
|
15141
|
-
|
15142
|
-
|
15143
|
-
|
15144
|
-
|
14378
|
+
function createDummyVideoStreamTrack() {
|
14379
|
+
let width = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 16;
|
14380
|
+
let height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 16;
|
14381
|
+
let enabled = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
14382
|
+
let paintContent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
14383
|
+
const canvas = document.createElement('canvas');
|
14384
|
+
// the canvas size is set to 16 by default, because electron apps seem to fail with smaller values
|
14385
|
+
canvas.width = width;
|
14386
|
+
canvas.height = height;
|
14387
|
+
const ctx = canvas.getContext('2d');
|
14388
|
+
ctx === null || ctx === void 0 ? void 0 : ctx.fillRect(0, 0, canvas.width, canvas.height);
|
14389
|
+
if (paintContent && ctx) {
|
14390
|
+
ctx.beginPath();
|
14391
|
+
ctx.arc(width / 2, height / 2, 50, 0, Math.PI * 2, true);
|
14392
|
+
ctx.closePath();
|
14393
|
+
ctx.fillStyle = 'grey';
|
14394
|
+
ctx.fill();
|
15145
14395
|
}
|
15146
|
-
|
15147
|
-
|
15148
|
-
|
15149
|
-
|
14396
|
+
// @ts-ignore
|
14397
|
+
const dummyStream = canvas.captureStream();
|
14398
|
+
const [dummyTrack] = dummyStream.getTracks();
|
14399
|
+
if (!dummyTrack) {
|
14400
|
+
throw Error('Could not get empty media stream video track');
|
15150
14401
|
}
|
14402
|
+
dummyTrack.enabled = enabled;
|
14403
|
+
return dummyTrack;
|
15151
14404
|
}
|
15152
|
-
|
15153
|
-
|
15154
|
-
|
14405
|
+
let emptyAudioStreamTrack;
|
14406
|
+
function getEmptyAudioStreamTrack() {
|
14407
|
+
if (!emptyAudioStreamTrack) {
|
14408
|
+
// implementation adapted from https://blog.mozilla.org/webrtc/warm-up-with-replacetrack/
|
14409
|
+
const ctx = new AudioContext();
|
14410
|
+
const oscillator = ctx.createOscillator();
|
14411
|
+
const dst = ctx.createMediaStreamDestination();
|
14412
|
+
oscillator.connect(dst);
|
14413
|
+
oscillator.start();
|
14414
|
+
[emptyAudioStreamTrack] = dst.stream.getAudioTracks();
|
14415
|
+
if (!emptyAudioStreamTrack) {
|
14416
|
+
throw Error('Could not get empty media stream audio track');
|
14417
|
+
}
|
14418
|
+
emptyAudioStreamTrack.enabled = false;
|
15155
14419
|
}
|
14420
|
+
return emptyAudioStreamTrack;
|
15156
14421
|
}
|
15157
|
-
class
|
15158
|
-
constructor(
|
15159
|
-
|
14422
|
+
class Future {
|
14423
|
+
constructor(futureBase, onFinally) {
|
14424
|
+
this.onFinally = onFinally;
|
14425
|
+
this.promise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
14426
|
+
this.resolve = resolve;
|
14427
|
+
this.reject = reject;
|
14428
|
+
if (futureBase) {
|
14429
|
+
yield futureBase(resolve, reject);
|
14430
|
+
}
|
14431
|
+
})).finally(() => {
|
14432
|
+
var _a;
|
14433
|
+
return (_a = this.onFinally) === null || _a === void 0 ? void 0 : _a.call(this);
|
14434
|
+
});
|
15160
14435
|
}
|
15161
14436
|
}
|
15162
|
-
|
15163
|
-
|
15164
|
-
|
14437
|
+
/**
|
14438
|
+
* Creates and returns an analyser web audio node that is attached to the provided track.
|
14439
|
+
* Additionally returns a convenience method `calculateVolume` to perform instant volume readings on that track.
|
14440
|
+
* Call the returned `cleanup` function to close the audioContext that has been created for the instance of this helper
|
14441
|
+
*/
|
14442
|
+
function createAudioAnalyser(track, options) {
|
14443
|
+
const opts = Object.assign({
|
14444
|
+
cloneTrack: false,
|
14445
|
+
fftSize: 2048,
|
14446
|
+
smoothingTimeConstant: 0.8,
|
14447
|
+
minDecibels: -100,
|
14448
|
+
maxDecibels: -80
|
14449
|
+
}, options);
|
14450
|
+
const audioContext = getNewAudioContext();
|
14451
|
+
if (!audioContext) {
|
14452
|
+
throw new Error('Audio Context not supported on this browser');
|
15165
14453
|
}
|
14454
|
+
const streamTrack = opts.cloneTrack ? track.mediaStreamTrack.clone() : track.mediaStreamTrack;
|
14455
|
+
const mediaStreamSource = audioContext.createMediaStreamSource(new MediaStream([streamTrack]));
|
14456
|
+
const analyser = audioContext.createAnalyser();
|
14457
|
+
analyser.minDecibels = opts.minDecibels;
|
14458
|
+
analyser.maxDecibels = opts.maxDecibels;
|
14459
|
+
analyser.fftSize = opts.fftSize;
|
14460
|
+
analyser.smoothingTimeConstant = opts.smoothingTimeConstant;
|
14461
|
+
mediaStreamSource.connect(analyser);
|
14462
|
+
const dataArray = new Uint8Array(analyser.frequencyBinCount);
|
14463
|
+
/**
|
14464
|
+
* Calculates the current volume of the track in the range from 0 to 1
|
14465
|
+
*/
|
14466
|
+
const calculateVolume = () => {
|
14467
|
+
analyser.getByteFrequencyData(dataArray);
|
14468
|
+
let sum = 0;
|
14469
|
+
for (const amplitude of dataArray) {
|
14470
|
+
sum += Math.pow(amplitude / 255, 2);
|
14471
|
+
}
|
14472
|
+
const volume = Math.sqrt(sum / dataArray.length);
|
14473
|
+
return volume;
|
14474
|
+
};
|
14475
|
+
const cleanup = () => {
|
14476
|
+
audioContext.close();
|
14477
|
+
if (opts.cloneTrack) {
|
14478
|
+
streamTrack.stop();
|
14479
|
+
}
|
14480
|
+
};
|
14481
|
+
return {
|
14482
|
+
calculateVolume,
|
14483
|
+
analyser,
|
14484
|
+
cleanup
|
14485
|
+
};
|
15166
14486
|
}
|
15167
|
-
class
|
15168
|
-
constructor(
|
15169
|
-
|
14487
|
+
class Mutex {
|
14488
|
+
constructor() {
|
14489
|
+
this._locking = Promise.resolve();
|
14490
|
+
this._locks = 0;
|
15170
14491
|
}
|
15171
|
-
|
15172
|
-
|
15173
|
-
|
15174
|
-
|
14492
|
+
isLocked() {
|
14493
|
+
return this._locks > 0;
|
14494
|
+
}
|
14495
|
+
lock() {
|
14496
|
+
this._locks += 1;
|
14497
|
+
let unlockNext;
|
14498
|
+
const willLock = new Promise(resolve => unlockNext = () => {
|
14499
|
+
this._locks -= 1;
|
14500
|
+
resolve();
|
14501
|
+
});
|
14502
|
+
const willUnlock = this._locking.then(() => unlockNext);
|
14503
|
+
this._locking = this._locking.then(() => willLock);
|
14504
|
+
return willUnlock;
|
15175
14505
|
}
|
15176
14506
|
}
|
15177
|
-
|
15178
|
-
|
15179
|
-
|
15180
|
-
|
15181
|
-
|
15182
|
-
|
15183
|
-
|
15184
|
-
|
15185
|
-
|
15186
|
-
|
15187
|
-
|
15188
|
-
|
15189
|
-
|
15190
|
-
|
15191
|
-
|
15192
|
-
|
15193
|
-
|
15194
|
-
|
15195
|
-
|
15196
|
-
|
15197
|
-
|
14507
|
+
|
14508
|
+
var QueueTaskStatus;
|
14509
|
+
(function (QueueTaskStatus) {
|
14510
|
+
QueueTaskStatus[QueueTaskStatus["WAITING"] = 0] = "WAITING";
|
14511
|
+
QueueTaskStatus[QueueTaskStatus["RUNNING"] = 1] = "RUNNING";
|
14512
|
+
QueueTaskStatus[QueueTaskStatus["COMPLETED"] = 2] = "COMPLETED";
|
14513
|
+
})(QueueTaskStatus || (QueueTaskStatus = {}));
|
14514
|
+
class AsyncQueue {
|
14515
|
+
constructor() {
|
14516
|
+
this.pendingTasks = new Map();
|
14517
|
+
this.taskMutex = new Mutex();
|
14518
|
+
this.nextTaskIndex = 0;
|
14519
|
+
}
|
14520
|
+
run(task) {
|
14521
|
+
return __awaiter(this, void 0, void 0, function* () {
|
14522
|
+
const taskInfo = {
|
14523
|
+
id: this.nextTaskIndex++,
|
14524
|
+
enqueuedAt: Date.now(),
|
14525
|
+
status: QueueTaskStatus.WAITING
|
14526
|
+
};
|
14527
|
+
this.pendingTasks.set(taskInfo.id, taskInfo);
|
14528
|
+
const unlock = yield this.taskMutex.lock();
|
14529
|
+
try {
|
14530
|
+
taskInfo.executedAt = Date.now();
|
14531
|
+
taskInfo.status = QueueTaskStatus.RUNNING;
|
14532
|
+
return yield task();
|
14533
|
+
} finally {
|
14534
|
+
taskInfo.status = QueueTaskStatus.COMPLETED;
|
14535
|
+
this.pendingTasks.delete(taskInfo.id);
|
14536
|
+
unlock();
|
15198
14537
|
}
|
15199
|
-
|
15200
|
-
}
|
14538
|
+
});
|
15201
14539
|
}
|
15202
|
-
|
15203
|
-
|
15204
|
-
|
15205
|
-
|
15206
|
-
|
15207
|
-
|
15208
|
-
|
15209
|
-
|
15210
|
-
|
15211
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
15212
|
-
CriticalTimers.setTimeout = function () {
|
15213
|
-
return setTimeout(...arguments);
|
15214
|
-
};
|
15215
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
15216
|
-
CriticalTimers.setInterval = function () {
|
15217
|
-
return setInterval(...arguments);
|
15218
|
-
};
|
15219
|
-
CriticalTimers.clearTimeout = function () {
|
15220
|
-
return clearTimeout(...arguments);
|
15221
|
-
};
|
15222
|
-
CriticalTimers.clearInterval = function () {
|
15223
|
-
return clearInterval(...arguments);
|
15224
|
-
};
|
14540
|
+
flush() {
|
14541
|
+
return __awaiter(this, void 0, void 0, function* () {
|
14542
|
+
return this.run(() => __awaiter(this, void 0, void 0, function* () {}));
|
14543
|
+
});
|
14544
|
+
}
|
14545
|
+
snapshot() {
|
14546
|
+
return Array.from(this.pendingTasks.values());
|
14547
|
+
}
|
14548
|
+
}
|
15225
14549
|
|
15226
14550
|
const passThroughQueueSignals = ['syncState', 'trickle', 'offer', 'answer', 'simulate', 'leave'];
|
15227
14551
|
function canPassThroughQueue(req) {
|
@@ -23418,7 +22742,10 @@ class Room extends eventsExports.EventEmitter {
|
|
23418
22742
|
livekitLogger.warn('detected connection state mismatch', {
|
23419
22743
|
numFailures: consecutiveFailures
|
23420
22744
|
});
|
23421
|
-
if (consecutiveFailures >= 3)
|
22745
|
+
if (consecutiveFailures >= 3) {
|
22746
|
+
this.recreateEngine();
|
22747
|
+
this.handleDisconnect(this.options.stopLocalTrackOnUnpublish, DisconnectReason.STATE_MISMATCH);
|
22748
|
+
}
|
23422
22749
|
} else {
|
23423
22750
|
consecutiveFailures = 0;
|
23424
22751
|
}
|